aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2011-11-30 05:16:36 +0000
committerJeff Law <law@redhat.com>2011-11-30 05:16:36 +0000
commit7b5177cc9956a68a50825c443a6d396fdc1af2b5 (patch)
treea6b80dca8f72a2e7640e4d535901e42325b2a954
parent6377b0d9b395f395e25bd4a030a9056171433061 (diff)
parentee4a734e5eece9824adc2a26e518c99bbdbe802e (diff)
Weekly merge from trunk. No regressions.reload-v2a
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/reload-v2a@181834 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--ChangeLog19
-rw-r--r--MAINTAINERS6
-rw-r--r--boehm-gc/ChangeLog4
-rwxr-xr-xboehm-gc/configure12
-rw-r--r--config/ChangeLog4
-rw-r--r--config/weakref.m448
-rwxr-xr-xconfigure4
-rw-r--r--configure.ac4
-rw-r--r--contrib/ChangeLog4
-rw-r--r--contrib/make_sunver.pl3
-rw-r--r--fixincludes/ChangeLog6
-rw-r--r--fixincludes/fixincl.x100
-rw-r--r--fixincludes/inclhack.def29
-rw-r--r--fixincludes/tests/base/pthread.h14
-rw-r--r--gcc/ChangeLog1169
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/ada/ChangeLog760
-rw-r--r--gcc/ada/Make-generated.in2
-rw-r--r--gcc/ada/Makefile.rtl6
-rw-r--r--gcc/ada/a-cbdlli.adb219
-rw-r--r--gcc/ada/a-cbhama.adb63
-rw-r--r--gcc/ada/a-cbhase.adb51
-rw-r--r--gcc/ada/a-cbmutr.adb101
-rw-r--r--gcc/ada/a-cborma.adb164
-rw-r--r--gcc/ada/a-cborma.ads13
-rw-r--r--gcc/ada/a-cborse.adb167
-rw-r--r--gcc/ada/a-cborse.ads8
-rw-r--r--gcc/ada/a-cdlili.adb178
-rw-r--r--gcc/ada/a-cdlili.ads2
-rw-r--r--gcc/ada/a-cfdlli.adb68
-rw-r--r--gcc/ada/a-cidlli.adb178
-rw-r--r--gcc/ada/a-cidlli.ads2
-rw-r--r--gcc/ada/a-cihama.adb67
-rw-r--r--gcc/ada/a-cihama.ads5
-rw-r--r--gcc/ada/a-cihase.adb52
-rw-r--r--gcc/ada/a-cimutr.adb103
-rw-r--r--gcc/ada/a-cimutr.ads4
-rw-r--r--gcc/ada/a-ciorma.adb184
-rw-r--r--gcc/ada/a-ciorma.ads8
-rw-r--r--gcc/ada/a-ciorse.adb166
-rw-r--r--gcc/ada/a-ciorse.ads6
-rw-r--r--gcc/ada/a-cobove.adb54
-rw-r--r--gcc/ada/a-cohama.adb68
-rw-r--r--gcc/ada/a-cohama.ads2
-rw-r--r--gcc/ada/a-cohase.adb42
-rw-r--r--gcc/ada/a-cohase.ads19
-rw-r--r--gcc/ada/a-coinve.adb89
-rw-r--r--gcc/ada/a-coinve.ads2
-rw-r--r--gcc/ada/a-comutr.adb97
-rw-r--r--gcc/ada/a-comutr.ads4
-rw-r--r--gcc/ada/a-convec.adb81
-rw-r--r--gcc/ada/a-convec.ads2
-rw-r--r--gcc/ada/a-coorma.adb167
-rw-r--r--gcc/ada/a-coorma.ads14
-rw-r--r--gcc/ada/a-coorse.adb166
-rw-r--r--gcc/ada/a-coorse.ads6
-rw-r--r--gcc/ada/a-exetim-posix.adb4
-rw-r--r--gcc/ada/a-finali.ads6
-rw-r--r--gcc/ada/adaint.c8
-rwxr-xr-xgcc/ada/aspects.adb6
-rwxr-xr-xgcc/ada/aspects.ads3
-rw-r--r--gcc/ada/checks.adb34
-rw-r--r--gcc/ada/env.c2
-rw-r--r--gcc/ada/errout.adb47
-rw-r--r--gcc/ada/errout.ads3
-rw-r--r--gcc/ada/erroutc.adb25
-rw-r--r--gcc/ada/erroutc.ads5
-rw-r--r--gcc/ada/exp_attr.adb129
-rw-r--r--gcc/ada/exp_ch5.adb44
-rw-r--r--gcc/ada/exp_ch6.adb84
-rw-r--r--gcc/ada/exp_imgv.adb131
-rw-r--r--gcc/ada/exp_intr.adb4
-rw-r--r--gcc/ada/exp_prag.adb9
-rw-r--r--gcc/ada/exp_util.adb8
-rw-r--r--gcc/ada/freeze.adb13
-rw-r--r--gcc/ada/frontend.adb6
-rw-r--r--gcc/ada/g-exptty.adb309
-rw-r--r--gcc/ada/g-exptty.ads131
-rw-r--r--gcc/ada/g-htable.ads175
-rw-r--r--gcc/ada/g-tty.adb134
-rw-r--r--gcc/ada/g-tty.ads73
-rw-r--r--gcc/ada/gcc-interface/Make-lang.in306
-rw-r--r--gcc/ada/gcc-interface/Makefile.in22
-rw-r--r--gcc/ada/gcc-interface/decl.c179
-rw-r--r--gcc/ada/gcc-interface/trans.c226
-rw-r--r--gcc/ada/gcc-interface/utils.c16
-rw-r--r--gcc/ada/gcc-interface/utils2.c8
-rw-r--r--gcc/ada/gnat_rm.texi26
-rw-r--r--gcc/ada/gnat_ugn.texi68
-rw-r--r--gcc/ada/impunit.adb2
-rw-r--r--gcc/ada/init.c23
-rw-r--r--gcc/ada/layout.adb102
-rw-r--r--gcc/ada/lib-load.adb19
-rw-r--r--gcc/ada/lib-load.ads3
-rw-r--r--gcc/ada/lib-xref.adb10
-rw-r--r--gcc/ada/lib.ads4
-rw-r--r--gcc/ada/mlib-tgt-specific-darwin.adb12
-rw-r--r--gcc/ada/mlib-tgt-specific-vxworks.adb6
-rw-r--r--gcc/ada/opt.ads5
-rw-r--r--gcc/ada/par-ch4.adb5
-rw-r--r--gcc/ada/par-ch6.adb6
-rw-r--r--gcc/ada/par-prag.adb1
-rw-r--r--gcc/ada/par-util.adb2
-rw-r--r--gcc/ada/prj-part.adb115
-rw-r--r--gcc/ada/prj-pp.adb11
-rw-r--r--gcc/ada/prj-pp.ads7
-rw-r--r--gcc/ada/restrict.adb147
-rw-r--r--gcc/ada/restrict.ads92
-rw-r--r--gcc/ada/rtsfind.ads2
-rw-r--r--gcc/ada/s-atocou-builtin.adb14
-rw-r--r--gcc/ada/s-finmas.adb6
-rwxr-xr-xgcc/ada/s-os_lib.ads2
-rw-r--r--gcc/ada/s-oscons-tmplt.c152
-rw-r--r--gcc/ada/s-osinte-aix.ads9
-rw-r--r--gcc/ada/s-osinte-darwin.ads9
-rw-r--r--gcc/ada/s-osinte-freebsd.ads12
-rw-r--r--gcc/ada/s-osinte-hpux-dce.ads6
-rw-r--r--gcc/ada/s-osinte-hpux.ads9
-rw-r--r--gcc/ada/s-osinte-irix.ads11
-rw-r--r--gcc/ada/s-osinte-lynxos-3.ads7
-rw-r--r--gcc/ada/s-osinte-lynxos.ads9
-rw-r--r--gcc/ada/s-osinte-solaris-posix.ads9
-rw-r--r--gcc/ada/s-osinte-solaris.ads7
-rw-r--r--gcc/ada/s-osinte-tru64.ads9
-rw-r--r--gcc/ada/s-osinte-vxworks.ads7
-rw-r--r--gcc/ada/s-osprim-vxworks.adb7
-rw-r--r--gcc/ada/s-rident.ads12
-rw-r--r--gcc/ada/s-stposu.adb58
-rw-r--r--gcc/ada/s-stposu.ads7
-rw-r--r--gcc/ada/s-taprop-hpux-dce.adb4
-rw-r--r--gcc/ada/s-taprop-irix.adb24
-rw-r--r--gcc/ada/s-taprop-linux.adb57
-rw-r--r--gcc/ada/s-taprop-posix.adb24
-rw-r--r--gcc/ada/s-taprop-solaris.adb12
-rw-r--r--gcc/ada/s-taprop-tru64.adb12
-rw-r--r--gcc/ada/s-taprop-vms.adb8
-rw-r--r--gcc/ada/s-taprop-vxworks.adb4
-rwxr-xr-xgcc/ada/s-utf_32.adb3
-rw-r--r--gcc/ada/sem.adb27
-rw-r--r--gcc/ada/sem_attr.adb42
-rw-r--r--gcc/ada/sem_ch10.adb27
-rw-r--r--gcc/ada/sem_ch12.adb20
-rw-r--r--gcc/ada/sem_ch13.adb64
-rw-r--r--gcc/ada/sem_ch3.adb58
-rw-r--r--gcc/ada/sem_ch4.adb4
-rw-r--r--gcc/ada/sem_ch5.adb298
-rw-r--r--gcc/ada/sem_ch6.adb118
-rw-r--r--gcc/ada/sem_ch8.adb8
-rw-r--r--gcc/ada/sem_ch9.adb77
-rw-r--r--gcc/ada/sem_elab.adb27
-rw-r--r--gcc/ada/sem_prag.adb144
-rw-r--r--gcc/ada/sem_res.adb62
-rw-r--r--gcc/ada/sem_util.adb44
-rw-r--r--gcc/ada/sem_util.ads12
-rw-r--r--gcc/ada/sinfo.adb18
-rw-r--r--gcc/ada/sinfo.ads25
-rw-r--r--gcc/ada/sinput.ads73
-rw-r--r--gcc/ada/snames.ads-tmpl2
-rw-r--r--gcc/ada/sysdep.c73
-rw-r--r--gcc/ada/terminals.c1551
-rw-r--r--gcc/ada/thread.c57
-rw-r--r--gcc/ada/types.ads8
-rw-r--r--gcc/ada/vms_data.ads43
-rw-r--r--gcc/builtins.c157
-rw-r--r--gcc/c-decl.c5
-rw-r--r--gcc/c-family/ChangeLog10
-rw-r--r--gcc/c-family/c-common.c58
-rw-r--r--gcc/c-family/c-pragma.c3
-rw-r--r--gcc/c-family/c-pragma.h2
-rw-r--r--gcc/c-parser.c9
-rw-r--r--gcc/calls.c2
-rw-r--r--gcc/cfgrtl.c13
-rw-r--r--gcc/common.opt2
-rw-r--r--gcc/config/alpha/alpha-protos.h17
-rw-r--r--gcc/config/alpha/alpha.c278
-rw-r--r--gcc/config/alpha/alpha.md1
-rw-r--r--gcc/config/alpha/constraints.md6
-rw-r--r--gcc/config/alpha/predicates.md5
-rw-r--r--gcc/config/alpha/sync.md311
-rw-r--r--gcc/config/arm/arm.c56
-rw-r--r--gcc/config/avr/avr-c.c40
-rw-r--r--gcc/config/avr/avr-devices.c36
-rw-r--r--gcc/config/avr/avr-log.c95
-rw-r--r--gcc/config/avr/avr-protos.h25
-rw-r--r--gcc/config/avr/avr.c2840
-rw-r--r--gcc/config/avr/avr.h28
-rw-r--r--gcc/config/avr/avr.md831
-rw-r--r--gcc/config/avr/predicates.md12
-rw-r--r--gcc/config/cris/cris-protos.h2
-rw-r--r--gcc/config/cris/cris.c5
-rw-r--r--gcc/config/cris/cris.h6
-rw-r--r--gcc/config/darwin-protos.h1
-rw-r--r--gcc/config/darwin.c8
-rw-r--r--gcc/config/darwin.h22
-rw-r--r--gcc/config/darwin9.h6
-rw-r--r--gcc/config/epiphany/epiphany.md2
-rw-r--r--gcc/config/host-linux.c4
-rw-r--r--gcc/config/i386/darwin.h3
-rw-r--r--gcc/config/i386/emmintrin.h8
-rw-r--r--gcc/config/i386/i386-builtin-types.def7
-rw-r--r--gcc/config/i386/i386-opts.h3
-rw-r--r--gcc/config/i386/i386.c1263
-rw-r--r--gcc/config/i386/i386.h8
-rw-r--r--gcc/config/i386/i386.md101
-rw-r--r--gcc/config/i386/i386.opt3
-rw-r--r--gcc/config/i386/i386elf.h8
-rw-r--r--gcc/config/i386/mmx.md18
-rw-r--r--gcc/config/i386/sse.md373
-rw-r--r--gcc/config/i386/sync.md113
-rw-r--r--gcc/config/ia64/ia64-protos.h3
-rw-r--r--gcc/config/ia64/ia64.c75
-rw-r--r--gcc/config/ia64/ia64.md106
-rw-r--r--gcc/config/ia64/sync.md310
-rw-r--r--gcc/config/m68k/linux.h4
-rw-r--r--gcc/config/m68k/m68k.c8
-rw-r--r--gcc/config/m68k/m68k.md9
-rw-r--r--gcc/config/m68k/sync.md80
-rw-r--r--gcc/config/mips/mips-protos.h3
-rw-r--r--gcc/config/mips/mips.c78
-rw-r--r--gcc/config/mips/mips.md332
-rw-r--r--gcc/config/mips/predicates.md9
-rw-r--r--gcc/config/pa/pa-linux.h1
-rw-r--r--gcc/config/rs6000/rs6000-protos.h10
-rw-r--r--gcc/config/rs6000/rs6000.c679
-rw-r--r--gcc/config/rs6000/rs6000.md2
-rw-r--r--gcc/config/rs6000/sync.md704
-rw-r--r--gcc/config/sparc/sparc-protos.h2
-rw-r--r--gcc/config/sparc/sparc.c65
-rw-r--r--gcc/config/sparc/sparc.h18
-rw-r--r--gcc/config/vms/vms-c.c84
-rw-r--r--gcc/config/vms/vms.h3
-rwxr-xr-xgcc/configure28
-rw-r--r--gcc/configure.ac12
-rw-r--r--gcc/coverage.c37
-rw-r--r--gcc/cp/ChangeLog162
-rw-r--r--gcc/cp/class.c39
-rw-r--r--gcc/cp/cp-tree.def2
-rw-r--r--gcc/cp/cp-tree.h12
-rw-r--r--gcc/cp/decl.c53
-rw-r--r--gcc/cp/error.c1
-rw-r--r--gcc/cp/init.c4
-rw-r--r--gcc/cp/name-lookup.c139
-rw-r--r--gcc/cp/parser.c215
-rw-r--r--gcc/cp/pt.c134
-rw-r--r--gcc/cp/ptree.c4
-rw-r--r--gcc/cp/search.c42
-rw-r--r--gcc/cp/semantics.c31
-rw-r--r--gcc/cp/tree.c2
-rw-r--r--gcc/cp/typeck.c26
-rw-r--r--gcc/cprop.c56
-rw-r--r--gcc/doc/contrib.texi4
-rw-r--r--gcc/doc/extend.texi31
-rw-r--r--gcc/doc/install.texi3
-rw-r--r--gcc/doc/invoke.texi26
-rw-r--r--gcc/doc/tm.texi4
-rw-r--r--gcc/doc/tm.texi.in2
-rw-r--r--gcc/expr.c11
-rw-r--r--gcc/expr.h6
-rw-r--r--gcc/final.c29
-rw-r--r--gcc/flag-types.h6
-rw-r--r--gcc/fold-const.c9
-rw-r--r--gcc/fortran/ChangeLog102
-rw-r--r--gcc/fortran/class.c3
-rw-r--r--gcc/fortran/decl.c179
-rw-r--r--gcc/fortran/gfortran.h4
-rw-r--r--gcc/fortran/interface.c26
-rw-r--r--gcc/fortran/match.c3
-rw-r--r--gcc/fortran/match.h2
-rw-r--r--gcc/fortran/module.c116
-rw-r--r--gcc/fortran/parse.c6
-rw-r--r--gcc/fortran/primary.c339
-rw-r--r--gcc/fortran/resolve.c116
-rw-r--r--gcc/fortran/symbol.c254
-rw-r--r--gcc/fortran/trans-array.c11
-rw-r--r--gcc/fortran/trans-decl.c44
-rw-r--r--gcc/fortran/trans-stmt.c3
-rw-r--r--gcc/fortran/trans-types.c7
-rw-r--r--gcc/fortran/trans.h1
-rw-r--r--gcc/function.c3
-rw-r--r--gcc/gcov.c20
-rw-r--r--gcc/gimple-streamer-in.c4
-rw-r--r--gcc/gimple-streamer-out.c5
-rw-r--r--gcc/gimple.c12
-rw-r--r--gcc/hard-reg-set.h11
-rw-r--r--gcc/incpath.c9
-rw-r--r--gcc/incpath.h1
-rw-r--r--gcc/ipa-cp.c35
-rw-r--r--gcc/ipa-inline-analysis.c176
-rw-r--r--gcc/ipa-inline.h1
-rw-r--r--gcc/ipa-prop.h7
-rw-r--r--gcc/ira.c5
-rw-r--r--gcc/java/ChangeLog5
-rw-r--r--gcc/java/lang.c4
-rw-r--r--gcc/jump.c13
-rw-r--r--gcc/lto-cgraph.c2
-rw-r--r--gcc/lto/ChangeLog5
-rw-r--r--gcc/lto/lto-lang.c17
-rw-r--r--gcc/omp-low.c4
-rw-r--r--gcc/optabs.c323
-rw-r--r--gcc/optabs.h4
-rw-r--r--gcc/opts.c2
-rw-r--r--gcc/output.h2
-rw-r--r--gcc/postreload.c18
-rw-r--r--gcc/recog.c28
-rw-r--r--gcc/reginfo.c28
-rw-r--r--gcc/reorg.c4
-rw-r--r--gcc/sched-deps.c10
-rw-r--r--gcc/target.def7
-rw-r--r--gcc/testsuite/ChangeLog573
-rw-r--r--gcc/testsuite/c-c++-common/dfp/pr33466.c12
-rw-r--r--gcc/testsuite/c-c++-common/tm/malloc.c4
-rw-r--r--gcc/testsuite/c-c++-common/tm/trxn-expr-3.c14
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle41.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-13.C24
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-15.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-16.C28
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto27.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype36.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/forw_enum10.C31
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice5.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr51150.C20
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr51216.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae11.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae26.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae30.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/trailing2.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-args-neg.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-implicit-conv-neg.C63
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-raw-length.C27
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-raw-op-string-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C40
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic120.C24
-rw-r--r--gcc/testsuite/g++.dg/debug/using4.C24
-rw-r--r--gcc/testsuite/g++.dg/debug/using5.C23
-rw-r--r--gcc/testsuite/g++.dg/debug/using6.C22
-rw-r--r--gcc/testsuite/g++.dg/eh/array1.C6
-rw-r--r--gcc/testsuite/g++.dg/ext/attrib27.C2
-rw-r--r--gcc/testsuite/g++.dg/gcov/gcov-10.C20
-rw-r--r--gcc/testsuite/g++.dg/gcov/gcov-11.C42
-rw-r--r--gcc/testsuite/g++.dg/gcov/gcov-8.C14
-rw-r--r--gcc/testsuite/g++.dg/gcov/gcov-9.C17
-rw-r--r--gcc/testsuite/g++.dg/inherit/using4.C4
-rw-r--r--gcc/testsuite/g++.dg/ipa/pr50605.C40
-rw-r--r--gcc/testsuite/g++.dg/lookup/name-clash9.C4
-rw-r--r--gcc/testsuite/g++.dg/lookup/pr6936.C23
-rw-r--r--gcc/testsuite/g++.dg/lookup/struct1.C4
-rw-r--r--gcc/testsuite/g++.dg/lookup/using24.C12
-rw-r--r--gcc/testsuite/g++.dg/lookup/using25.C28
-rw-r--r--gcc/testsuite/g++.dg/lookup/using26.C27
-rw-r--r--gcc/testsuite/g++.dg/lookup/using27.C48
-rw-r--r--gcc/testsuite/g++.dg/lookup/using28.C11
-rw-r--r--gcc/testsuite/g++.dg/lookup/using29.C81
-rw-r--r--gcc/testsuite/g++.dg/lookup/using30.C8
-rw-r--r--gcc/testsuite/g++.dg/lookup/using31.C8
-rw-r--r--gcc/testsuite/g++.dg/lookup/using32.C9
-rw-r--r--gcc/testsuite/g++.dg/lookup/using33.C26
-rw-r--r--gcc/testsuite/g++.dg/lookup/using34.C10
-rw-r--r--gcc/testsuite/g++.dg/lookup/using35.C11
-rw-r--r--gcc/testsuite/g++.dg/lookup/using36.C31
-rw-r--r--gcc/testsuite/g++.dg/lookup/using37.C22
-rw-r--r--gcc/testsuite/g++.dg/lookup/using38.C23
-rw-r--r--gcc/testsuite/g++.dg/lookup/using39.C63
-rw-r--r--gcc/testsuite/g++.dg/lookup/using40.C28
-rw-r--r--gcc/testsuite/g++.dg/lookup/using41.C21
-rw-r--r--gcc/testsuite/g++.dg/lookup/using42.C26
-rw-r--r--gcc/testsuite/g++.dg/lookup/using44.C28
-rw-r--r--gcc/testsuite/g++.dg/lookup/using45.C33
-rw-r--r--gcc/testsuite/g++.dg/lookup/using46.C62
-rw-r--r--gcc/testsuite/g++.dg/lookup/using47.C29
-rw-r--r--gcc/testsuite/g++.dg/lookup/using48.C23
-rw-r--r--gcc/testsuite/g++.dg/lookup/using49.C20
-rw-r--r--gcc/testsuite/g++.dg/other/pr49912.C38
-rw-r--r--gcc/testsuite/g++.dg/parse/ctor5.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/elab1.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/elab2.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/int-as-enum1.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/typedef1.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/typedef3.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/typedef4.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/typedef5.C2
-rw-r--r--gcc/testsuite/g++.dg/template/crash26.C2
-rw-r--r--gcc/testsuite/g++.dg/template/error46.C11
-rw-r--r--gcc/testsuite/g++.dg/template/nontype4.C2
-rw-r--r--gcc/testsuite/g++.dg/template/static4.C2
-rw-r--r--gcc/testsuite/g++.dg/template/typedef1.C2
-rw-r--r--gcc/testsuite/g++.dg/template/unify11.C8
-rw-r--r--gcc/testsuite/g++.dg/template/using2.C15
-rw-r--r--gcc/testsuite/g++.dg/template/virtual2.C11
-rw-r--r--gcc/testsuite/g++.dg/tm/pr47747.C21
-rw-r--r--gcc/testsuite/g++.dg/tm/template-1.C3
-rw-r--r--gcc/testsuite/g++.dg/tm/template-2.C22
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr50741.C14
-rw-r--r--gcc/testsuite/g++.dg/warn/Wzero-as-null-pointer-constant-3.C22
-rw-r--r--gcc/testsuite/g++.old-deja/g++.benjamin/typedef01.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/line1.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/misc14.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900127_02.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/scoping16.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/anon7.C6
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/elab1.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/redecl1.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/syntax4.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/typedef7.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/using1.C6
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr44707.c2
-rw-r--r--gcc/testsuite/gcc.dg/atomic-compare-exchange-4.c3
-rw-r--r--gcc/testsuite/gcc.dg/atomic-compare-exchange-5.c4
-rw-r--r--gcc/testsuite/gcc.dg/atomic-exchange-4.c3
-rw-r--r--gcc/testsuite/gcc.dg/atomic-exchange-5.c4
-rw-r--r--gcc/testsuite/gcc.dg/atomic-generic-aux.c21
-rw-r--r--gcc/testsuite/gcc.dg/atomic-generic.c4
-rw-r--r--gcc/testsuite/gcc.dg/atomic-load-4.c3
-rw-r--r--gcc/testsuite/gcc.dg/atomic-load-5.c4
-rw-r--r--gcc/testsuite/gcc.dg/atomic-noinline-aux.c10
-rw-r--r--gcc/testsuite/gcc.dg/atomic-noinline.c2
-rw-r--r--gcc/testsuite/gcc.dg/atomic-op-4.c3
-rw-r--r--gcc/testsuite/gcc.dg/atomic-op-5.c4
-rw-r--r--gcc/testsuite/gcc.dg/atomic-pr51256.c47
-rw-r--r--gcc/testsuite/gcc.dg/atomic-store-4.c3
-rw-r--r--gcc/testsuite/gcc.dg/atomic-store-5.c4
-rw-r--r--gcc/testsuite/gcc.dg/autopar/pr49960-1.c36
-rw-r--r--gcc/testsuite/gcc.dg/autopar/pr49960.c49
-rw-r--r--gcc/testsuite/gcc.dg/cpp/assert4.c4
-rw-r--r--gcc/testsuite/gcc.dg/delay-slot-2.c116
-rw-r--r--gcc/testsuite/gcc.dg/di-longlong64-sync-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/di-sync-multithread.c3
-rw-r--r--gcc/testsuite/gcc.dg/lto/trans-mem-1_0.c12
-rw-r--r--gcc/testsuite/gcc.dg/lto/trans-mem-1_1.c9
-rw-r--r--gcc/testsuite/gcc.dg/lto/trans-mem-2_0.c22
-rw-r--r--gcc/testsuite/gcc.dg/lto/trans-mem-2_1.c4
-rw-r--r--gcc/testsuite/gcc.dg/pr43864-2.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr43864-3.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr43864-4.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr43864.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr50290.c27
-rw-r--r--gcc/testsuite/gcc.dg/pr50764.c17
-rw-r--r--gcc/testsuite/gcc.dg/pr50765.c10
-rw-r--r--gcc/testsuite/gcc.dg/pr50827.c17
-rw-r--r--gcc/testsuite/gcc.dg/pr51261.c9
-rw-r--r--gcc/testsuite/gcc.dg/simulate-thread/atomic-load-int128.c2
-rw-r--r--gcc/testsuite/gcc.dg/simulate-thread/atomic-load-longlong.c3
-rw-r--r--gcc/testsuite/gcc.dg/simulate-thread/atomic-other-int128.c4
-rw-r--r--gcc/testsuite/gcc.dg/simulate-thread/atomic-other-longlong.c3
-rw-r--r--gcc/testsuite/gcc.dg/tm/20100615.c3
-rw-r--r--gcc/testsuite/gcc.dg/tm/memopt-13.c1
-rw-r--r--gcc/testsuite/gcc.dg/tm/memopt-6.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/fast-math-bb-slp-call-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/fast-math-vect-call-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr30858.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr51074.c24
-rw-r--r--gcc/testsuite/gcc.dg/volatile-bitfields-1.c23
-rw-r--r--gcc/testsuite/gcc.dg/vshift-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/vshift-3.c4
-rw-r--r--gcc/testsuite/gcc.misc-tests/gcov-13.c1
-rw-r--r--gcc/testsuite/gcc.misc-tests/gcov-16.c12
-rw-r--r--gcc/testsuite/gcc.misc-tests/gcov-17.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/pr49641.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-ceil-sfix-2-vec.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-ceil-sfix-vec.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-ceil-vec.c51
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-ceilf-sfix-vec.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-ceilf-vec.c51
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-copysign-vec.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-copysignf-vec.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-cvt-2-vec.c60
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-cvt-vec.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-floor-sfix-2-vec.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-floor-sfix-vec.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-floor-vec.c51
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-floorf-sfix-vec.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-floorf-vec.c51
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-lrint-vec.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-lrintf-vec.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-recip-vec.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-rint-sfix-2-vec.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-rint-sfix-vec.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-rint-vec.c51
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-rintf-sfix-vec.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-rintf-vec.c51
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-round-sfix-2-vec.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-round-sfix-vec.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-round-vec.c51
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-roundf-sfix-vec.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-roundf-vec.c51
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-trunc-vec.c51
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-truncf-vec.c51
-rw-r--r--gcc/testsuite/gcc.target/i386/pr51235.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/pr51236.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-copysignf-vec.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-recip-vec.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-copysign-vec.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-cvt-vec.c60
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-lrint-vec.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-lrintf-vec.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-ceil-sfix-vec.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-ceil-vec.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-ceilf-sfix-vec.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-ceilf-vec.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-floor-sfix-vec.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-floor-vec.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-floorf-sfix-vec.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-floorf-vec.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-rint-sfix-vec.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-rint-vec.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-rintf-sfix-vec.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-rintf-vec.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-round-sfix-vec.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-round-vec.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-roundf-sfix-vec.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-roundf-vec.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-trunc-vec.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-truncf-vec.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sw-1.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/div-1.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/div-10.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/div-11.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/div-12.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/div-2.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/div-3.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/div-4.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/div-5.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/div-6.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/div-7.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/div-8.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/div-9.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/fix-r4000-1.c4
-rw-r--r--gcc/testsuite/gcc.target/mips/fix-r4000-10.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/fix-r4000-11.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/fix-r4000-12.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/fix-r4000-2.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/fix-r4000-3.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/fix-r4000-4.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/fix-r4000-5.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/fix-r4000-6.c4
-rw-r--r--gcc/testsuite/gcc.target/mips/fix-r4000-7.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/fix-r4000-8.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/fix-r4000-9.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/mips.exp6
-rw-r--r--gcc/testsuite/gcc.target/mips/mult-10.c13
-rw-r--r--gcc/testsuite/gcc.target/mips/mult-11.c13
-rw-r--r--gcc/testsuite/gcc.target/mips/mult-12.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/mult-13.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/mult-14.c15
-rw-r--r--gcc/testsuite/gcc.target/mips/mult-15.c15
-rw-r--r--gcc/testsuite/gcc.target/mips/mult-16.c13
-rw-r--r--gcc/testsuite/gcc.target/mips/mult-17.c13
-rw-r--r--gcc/testsuite/gcc.target/mips/mult-18.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/mult-19.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/mult-2.c13
-rw-r--r--gcc/testsuite/gcc.target/mips/mult-3.c13
-rw-r--r--gcc/testsuite/gcc.target/mips/mult-4.c13
-rw-r--r--gcc/testsuite/gcc.target/mips/mult-5.c13
-rw-r--r--gcc/testsuite/gcc.target/mips/mult-6.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/mult-7.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/mult-8.c15
-rw-r--r--gcc/testsuite/gcc.target/mips/mult-9.c15
-rw-r--r--gcc/testsuite/gcc.target/mips/no-dsp-1.c7
-rw-r--r--gcc/testsuite/gcc.target/mips/soft-float-1.c7
-rw-r--r--gcc/testsuite/gfortran.dg/c_ptr_tests_17.f9088
-rw-r--r--gcc/testsuite/gfortran.dg/c_ptr_tests_18.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/constructor_1.f9042
-rw-r--r--gcc/testsuite/gfortran.dg/constructor_2.f9073
-rw-r--r--gcc/testsuite/gfortran.dg/constructor_3.f9047
-rw-r--r--gcc/testsuite/gfortran.dg/constructor_4.f9033
-rw-r--r--gcc/testsuite/gfortran.dg/constructor_5.f9034
-rw-r--r--gcc/testsuite/gfortran.dg/constructor_6.f90171
-rw-r--r--gcc/testsuite/gfortran.dg/function_types_3.f902
-rw-r--r--gcc/testsuite/gfortran.dg/implicit_pure_1.f9053
-rw-r--r--gcc/testsuite/gfortran.dg/inline_sum_3.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/iso_c_binding_compiler_4.f9018
-rw-r--r--gcc/testsuite/gfortran.dg/result_1.f907
-rw-r--r--gcc/testsuite/gfortran.dg/structure_constructor_3.f032
-rw-r--r--gcc/testsuite/gfortran.dg/structure_constructor_4.f032
-rw-r--r--gcc/testsuite/gfortran.dg/type_decl_3.f907
-rw-r--r--gcc/testsuite/gfortran.dg/use_only_5.f9038
-rw-r--r--gcc/testsuite/gfortran.dg/used_types_25.f9017
-rw-r--r--gcc/testsuite/gfortran.dg/used_types_26.f9022
-rw-r--r--gcc/testsuite/gfortran.dg/volatile13.f9011
-rw-r--r--gcc/testsuite/gfortran.dg/whole_file_35.f9028
-rw-r--r--gcc/testsuite/gnat.dg/discr32.adb21
-rw-r--r--gcc/testsuite/gnat.dg/discr32_pkg.ads24
-rw-r--r--gcc/testsuite/lib/gcc-simulate-thread.exp31
-rw-r--r--gcc/testsuite/lib/target-supports.exp103
-rw-r--r--gcc/toplev.c5
-rw-r--r--gcc/tracer.c9
-rw-r--r--gcc/trans-mem.c29
-rw-r--r--gcc/tree-data-ref.c61
-rw-r--r--gcc/tree-inline.c6
-rw-r--r--gcc/tree-inline.h3
-rw-r--r--gcc/tree-outof-ssa.c2
-rw-r--r--gcc/tree-ssa-live.c6
-rw-r--r--gcc/tree-ssa-tail-merge.c357
-rw-r--r--gcc/tree-vect-data-refs.c1
-rw-r--r--gcc/tree.c1
-rw-r--r--gcc/tree.def3
-rw-r--r--gcc/tree.h1
-rw-r--r--gcc/var-tracking.c2
-rw-r--r--gcc/varasm.c29
-rw-r--r--libada/ChangeLog2
-rw-r--r--libcpp/ChangeLog12
-rw-r--r--libcpp/expr.c4
-rw-r--r--libcpp/include/line-map.h10
-rw-r--r--libcpp/line-map.c90
-rw-r--r--libffi/ChangeLog4
-rwxr-xr-xlibffi/configure6
-rw-r--r--libgcc/ChangeLog139
-rw-r--r--libgcc/Makefile.in8
-rw-r--r--libgcc/config.host51
-rw-r--r--libgcc/config/alpha/qrnnd.S12
-rw-r--r--libgcc/config/arm/lib1funcs.S70
-rw-r--r--libgcc/config/avr/lib1funcs.S469
-rw-r--r--libgcc/config/avr/t-avr6
-rw-r--r--libgcc/config/darwin-crt-tm.c77
-rw-r--r--libgcc/config/i386/t-darwin642
-rw-r--r--libgcc/config/m68k/linux-atomic.c211
-rw-r--r--libgcc/config/m68k/t-linux1
-rw-r--r--libgcc/config/rs6000/t-ppccomm21
-rw-r--r--libgcc/config/rs6000/t-ppccomm-ldbl1
-rw-r--r--libgcc/config/rs6000/t-savresfgpr21
-rw-r--r--libgcc/config/sh/t-netbsd2
-rw-r--r--libgcc/config/t-darwin6
-rw-r--r--libgcc/crtstuff.c104
-rw-r--r--libgcc/generic-morestack.c76
-rw-r--r--libgcc/libgcc-std.ver.in2
-rw-r--r--libgcc/static-object.mk7
-rw-r--r--libgfortran/ChangeLog4
-rwxr-xr-xlibgfortran/configure12
-rw-r--r--libgo/Makefile.am25
-rw-r--r--libgo/Makefile.in206
-rw-r--r--libgo/go/syscall/mksyscall.awk11
-rw-r--r--libgo/runtime/cpuprof.c10
-rw-r--r--libgo/runtime/go-close.c6
-rw-r--r--libgo/runtime/go-defer.c8
-rw-r--r--libgo/runtime/go-deferred-recover.c5
-rw-r--r--libgo/runtime/go-go.c668
-rw-r--r--libgo/runtime/go-gomaxprocs.c23
-rw-r--r--libgo/runtime/go-lock-os-thread.c24
-rw-r--r--libgo/runtime/go-main.c61
-rw-r--r--libgo/runtime/go-nanotime.c2
-rw-r--r--libgo/runtime/go-note.c74
-rw-r--r--libgo/runtime/go-panic.c8
-rw-r--r--libgo/runtime/go-rand.c18
-rw-r--r--libgo/runtime/go-rec-nb-small.c11
-rw-r--r--libgo/runtime/go-rec-small.c4
-rw-r--r--libgo/runtime/go-recover.c6
-rw-r--r--libgo/runtime/go-sched.c15
-rw-r--r--libgo/runtime/go-select.c6
-rw-r--r--libgo/runtime/go-semacquire.c151
-rw-r--r--libgo/runtime/go-send-nb-small.c6
-rw-r--r--libgo/runtime/go-send-small.c7
-rw-r--r--libgo/runtime/go-signal.c113
-rw-r--r--libgo/runtime/go-signal.h7
-rw-r--r--libgo/runtime/go-unwind.c7
-rw-r--r--libgo/runtime/lock_futex.c146
-rw-r--r--libgo/runtime/lock_sema.c217
-rw-r--r--libgo/runtime/malloc.goc60
-rw-r--r--libgo/runtime/malloc.h3
-rw-r--r--libgo/runtime/mcentral.c1
-rw-r--r--libgo/runtime/mfinal.c50
-rw-r--r--libgo/runtime/mgc0.c254
-rw-r--r--libgo/runtime/mheap.c5
-rw-r--r--libgo/runtime/mprof.goc36
-rw-r--r--libgo/runtime/proc.c1352
-rw-r--r--libgo/runtime/runtime.c172
-rw-r--r--libgo/runtime/runtime.h233
-rw-r--r--libgo/runtime/runtime1.goc10
-rw-r--r--libgo/runtime/sema.goc181
-rw-r--r--libgo/runtime/sigqueue.goc5
-rw-r--r--libgo/runtime/string.goc18
-rw-r--r--libgo/runtime/thread-linux.c101
-rw-r--r--libgo/runtime/thread-sema.c74
-rw-r--r--libgo/runtime/thread.c159
-rw-r--r--libgomp/ChangeLog4
-rwxr-xr-xlibgomp/configure12
-rw-r--r--libitm/ChangeLog72
-rw-r--r--libitm/Makefile.am23
-rw-r--r--libitm/Makefile.in32
-rw-r--r--libitm/acinclude.m465
-rw-r--r--libitm/aclocal.m41
-rw-r--r--libitm/alloc_cpp.cc18
-rw-r--r--libitm/config.h.in3
-rw-r--r--libitm/config/generic/asmcfi.h2
-rw-r--r--libitm/config/x86/sjlj.S63
-rw-r--r--libitm/configure160
-rw-r--r--libitm/configure.ac2
-rw-r--r--libitm/eh_cpp.cc8
-rw-r--r--libitm/libitm_i.h8
-rw-r--r--libitm/testsuite/Makefile.in10
-rw-r--r--libitm/testsuite/lib/libitm.exp2
-rw-r--r--libitm/testsuite/libitm.c/memcpy-1.c6
-rw-r--r--libitm/testsuite/libitm.c/memset-1.c6
-rw-r--r--libjava/ChangeLog13
-rwxr-xr-xlibjava/configure16
-rw-r--r--libjava/configure.ac2
-rw-r--r--libjava/libltdl/ChangeLog5
-rw-r--r--libjava/libltdl/acinclude.m46
-rwxr-xr-xlibjava/libltdl/configure4
-rw-r--r--libjava/prims.cc14
-rw-r--r--libmudflap/ChangeLog4
-rwxr-xr-xlibmudflap/configure6
-rw-r--r--libobjc/ChangeLog4
-rwxr-xr-xlibobjc/configure6
-rw-r--r--libquadmath/ChangeLog4
-rwxr-xr-xlibquadmath/configure6
-rw-r--r--libssp/ChangeLog4
-rwxr-xr-xlibssp/configure6
-rw-r--r--libstdc++-v3/ChangeLog251
-rwxr-xr-xlibstdc++-v3/configure12
-rw-r--r--libstdc++-v3/doc/xml/faq.xml9
-rw-r--r--libstdc++-v3/doc/xml/manual/abi.xml4
-rw-r--r--libstdc++-v3/doc/xml/manual/appendix_contributing.xml25
-rw-r--r--libstdc++-v3/doc/xml/manual/backwards_compatibility.xml2
-rw-r--r--libstdc++-v3/doc/xml/manual/messages.xml5
-rw-r--r--libstdc++-v3/doc/xml/manual/shared_ptr.xml78
-rw-r--r--libstdc++-v3/doc/xml/manual/status_cxx2011.xml68
-rw-r--r--libstdc++-v3/doc/xml/manual/status_cxxtr1.xml16
-rw-r--r--libstdc++-v3/doc/xml/manual/using.xml2
-rw-r--r--libstdc++-v3/doc/xml/manual/utilities.xml2
-rw-r--r--libstdc++-v3/include/backward/binders.h9
-rw-r--r--libstdc++-v3/include/bits/atomic_base.h3
-rw-r--r--libstdc++-v3/include/bits/basic_string.h8
-rw-r--r--libstdc++-v3/include/bits/functional_hash.h75
-rw-r--r--libstdc++-v3/include/bits/hashtable.h810
-rw-r--r--libstdc++-v3/include/bits/hashtable_policy.h231
-rw-r--r--libstdc++-v3/include/bits/shared_ptr.h2
-rw-r--r--libstdc++-v3/include/bits/shared_ptr_base.h2
-rw-r--r--libstdc++-v3/include/bits/stl_bvector.h2
-rw-r--r--libstdc++-v3/include/bits/stl_map.h5
-rw-r--r--libstdc++-v3/include/bits/stl_multimap.h5
-rw-r--r--libstdc++-v3/include/bits/stl_tree.h10
-rw-r--r--libstdc++-v3/include/bits/unique_ptr.h2
-rw-r--r--libstdc++-v3/include/bits/unordered_map.h8
-rw-r--r--libstdc++-v3/include/bits/unordered_set.h8
-rw-r--r--libstdc++-v3/include/bits/vector.tcc2
-rw-r--r--libstdc++-v3/include/debug/bitset11
-rw-r--r--libstdc++-v3/include/debug/map.h4
-rw-r--r--libstdc++-v3/include/debug/multimap.h4
-rw-r--r--libstdc++-v3/include/debug/unordered_map16
-rw-r--r--libstdc++-v3/include/debug/unordered_set16
-rw-r--r--libstdc++-v3/include/debug/vector2
-rw-r--r--libstdc++-v3/include/ext/vstring.h8
-rw-r--r--libstdc++-v3/include/profile/bitset6
-rw-r--r--libstdc++-v3/include/profile/map.h4
-rw-r--r--libstdc++-v3/include/profile/multimap.h4
-rw-r--r--libstdc++-v3/include/profile/vector2
-rw-r--r--libstdc++-v3/include/std/bitset4
-rw-r--r--libstdc++-v3/include/std/functional69
-rw-r--r--libstdc++-v3/include/std/iomanip68
-rw-r--r--libstdc++-v3/include/std/system_error2
-rw-r--r--libstdc++-v3/include/std/thread2
-rw-r--r--libstdc++-v3/include/std/tuple50
-rw-r--r--libstdc++-v3/include/std/type_traits22
-rw-r--r--libstdc++-v3/include/std/typeindex4
-rw-r--r--libstdc++-v3/include/tr1/functional176
-rw-r--r--libstdc++-v3/include/tr1/hashtable.h4
-rw-r--r--libstdc++-v3/include/tr1/poly_hermite.tcc4
-rw-r--r--libstdc++-v3/libsupc++/eh_tm.cc2
-rw-r--r--libstdc++-v3/libsupc++/typeinfo2
-rw-r--r--libstdc++-v3/scripts/run_doxygen4
-rw-r--r--libstdc++-v3/src/compatibility-ldbl.cc11
-rw-r--r--libstdc++-v3/src/hash-long-double-aux.cc50
-rw-r--r--libstdc++-v3/src/hash-long-double-tr1-aux.cc56
-rw-r--r--libstdc++-v3/src/hash_c++0x.cc26
-rw-r--r--libstdc++-v3/src/hash_tr1.cc6
-rw-r--r--libstdc++-v3/testsuite/20_util/bind/cv_quals_3.cc65
-rw-r--r--libstdc++-v3/testsuite/20_util/bind/ref_neg.cc8
-rw-r--r--libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/is_constructible/51185.cc39
-rw-r--r--libstdc++-v3/testsuite/20_util/is_constructible/value-2.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc4
-rw-r--r--libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc4
-rw-r--r--libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string/cons/char/moveable2.cc1
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/moveable2.cc1
-rw-r--r--libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr-2.cc36
-rw-r--r--libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr.cc9
-rw-r--r--libstdc++-v3/testsuite/23_containers/map/modifiers/erase/51142.cc38
-rw-r--r--libstdc++-v3/testsuite/23_containers/multimap/modifiers/erase/51142.cc38
-rw-r--r--libstdc++-v3/testsuite/23_containers/multiset/modifiers/erase/51142.cc38
-rw-r--r--libstdc++-v3/testsuite/23_containers/set/modifiers/erase/51142.cc38
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/erase/51142.cc38
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/erase/51142.cc38
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/copy.cc45
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/1.cc24
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/24061-multiset.cc20
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/51142.cc38
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_range.cc19
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single_move.cc15
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/erase/51142.cc38
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/hash_policy/rehash.cc62
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/instantiation_neg.cc41
-rw-r--r--libstdc++-v3/testsuite/27_io/manipulators/extended/get_money/char/51288.cc48
-rw-r--r--libstdc++-v3/testsuite/27_io/manipulators/extended/get_money/wchar_t/51288.cc48
-rw-r--r--libstdc++-v3/testsuite/27_io/manipulators/extended/put_money/char/51288.cc49
-rw-r--r--libstdc++-v3/testsuite/27_io/manipulators/extended/put_money/wchar_t/51288.cc49
-rw-r--r--libstdc++-v3/testsuite/30_threads/future/cons/constexpr.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_future/cons/constexpr.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/native_handle/typesizes.cc6
-rw-r--r--libstdc++-v3/testsuite/performance/23_containers/copy_construct/unordered_set.cc43
-rw-r--r--libstdc++-v3/testsuite/tr1/3_function_objects/bind/cv_quals.cc53
-rw-r--r--libstdc++-v3/testsuite/tr1/3_function_objects/bind/mixed.cc139
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_tr1.h2
-rw-r--r--libtool.m48
-rw-r--r--lto-plugin/ChangeLog4
-rwxr-xr-xlto-plugin/configure6
-rw-r--r--maintainer-scripts/ChangeLog5
-rwxr-xr-xmaintainer-scripts/update_web_docs_svn1
-rw-r--r--zlib/ChangeLog.gcj4
-rwxr-xr-xzlib/configure6
815 files changed, 30223 insertions, 9780 deletions
diff --git a/ChangeLog b/ChangeLog
index e18fea2234f..e70df0cb9e1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2011-11-21 Eric Botcazou <ebotcazou@libertysurf.fr>
+
+ * MAINTAINERS: Add self as co-maintainer of the Ada front end.
+
+2011-11-21 Andreas Tobler <andreast@fgznet.ch>
+
+ * libtool.m4: dditional FreeBSD 10 fixes.
+
+2011-11-21 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * MAINTAINERS: Move myself from Write After Approval to CPU Port
+ Maintainers section, as Epiphany maintainer.
+
+2011-11-18 Iain Sandoe <iains@gcc.gnu.org>
+
+ PR target/49992
+ * configure.ac: Remove ranlib special-casing for Darwin.
+ * configure: Regenerate.
+
2011-11-12 Andrey Belevantsev <abel@ispras.ru>
* MAINTAINERS (Reviewers): Keep the list sorted.
diff --git a/MAINTAINERS b/MAINTAINERS
index 511c08ac104..d6af32eb8d6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -55,6 +55,7 @@ bfin port Bernd Schmidt bernds@codesourcery.com
bfin port Jie Zhang jzhang918@gmail.com
c6x port Bernd Schmidt bernds@codesourcery.com
cris port Hans-Peter Nilsson hp@axis.com
+epiphany port Joern Rennecke joern.rennecke@embecosm.com
fr30 port Nick Clifton nickc@redhat.com
frv port Nick Clifton nickc@redhat.com
frv port Alexandre Oliva aoliva@redhat.com
@@ -138,6 +139,7 @@ C front end/ISO C99 Richard Henderson rth@redhat.com
Ada front end Geert Bosch bosch@gnat.com
Ada front end Robert Dewar dewar@gnat.com
Ada front end Arnaud Charlet charlet@act-europe.fr
+Ada front end Eric Botcazou ebotcazou@libertysurf.fr
Fortran Paul Brook paul@codesourcery.com
c++ Jason Merrill jason@redhat.com
c++ Mark Mitchell mark@codesourcery.com
@@ -343,6 +345,7 @@ Ian Dall ian@beware.dropbear.id.au
David Daney david.daney@caviumnetworks.com
Bud Davis jmdavis@link.com
Chris Demetriou cgd@google.com
+Sameera Deshpande sameera.deshpande@arm.com
François Dumont fdumont@gcc.gnu.org
Benoit Dupont de Dinechin benoit.dupont-de-dinechin@st.com
Michael Eager eager@eagercon.com
@@ -419,6 +422,7 @@ Georg-Johann Lay avr@gjlay.de
Marc Lehmann pcg@goof.com
James Lemke jwlemke@juniper.net
Kriang Lerdsuwanakij lerdsuwa@users.sourceforge.net
+Jiangning Liu jiangning.liu@arm.com
Sa Liu saliu@de.ibm.com
Ralph Loader rcl@ihug.co.nz
Gabor Loki loki@inf.u-szeged.hu
@@ -467,8 +471,6 @@ Ramana Radhakrishnan ramana.radhakrishnan@arm.com
Easwaran Raman eraman@google.com
Rolf Rasmussen rolfwr@gcc.gnu.org
Volker Reichelt v.reichelt@netcologne.de
-Joern Rennecke amylaar@spamcop.net
-Joern Rennecke joern.rennecke@embecosm.com
Bernhard Reutner-Fischer rep.dot.nop@gmail.com
Tom Rix trix@redhat.com
Craig Rodrigues rodrigc@gcc.gnu.org
diff --git a/boehm-gc/ChangeLog b/boehm-gc/ChangeLog
index 15f079dd3a2..22ea666ce5e 100644
--- a/boehm-gc/ChangeLog
+++ b/boehm-gc/ChangeLog
@@ -1,3 +1,7 @@
+2011-11-21 Andreas Tobler <andreast@fgznet.ch>
+
+ * configure: Regenerate.
+
2011-08-08 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* configure.ac (THREADS): Remove posix95.
diff --git a/boehm-gc/configure b/boehm-gc/configure
index 632a229cdf2..a901e505b73 100755
--- a/boehm-gc/configure
+++ b/boehm-gc/configure
@@ -9518,7 +9518,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct=yes
hardcode_minus_L=yes
@@ -10434,7 +10434,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -10452,7 +10452,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
@@ -12342,7 +12342,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
esac
;;
- freebsd[12]*)
+ freebsd2.*)
# C++ shared libraries reported to be fairly broken before
# switch to ELF
ld_shlibs_CXX=no
@@ -14117,7 +14117,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -14135,7 +14135,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
diff --git a/config/ChangeLog b/config/ChangeLog
index 4f202ffbc9a..4ebecc32f70 100644
--- a/config/ChangeLog
+++ b/config/ChangeLog
@@ -1,3 +1,7 @@
+2011-11-22 Iain Sandoe <iains@gcc.gnu.org>
+
+ * weakref.m4: New file.
+
2011-11-09 Richard Henderson <rth@redhat.com>
* asmcfi.m4: New file.
diff --git a/config/weakref.m4 b/config/weakref.m4
new file mode 100644
index 00000000000..39b63d39b8a
--- /dev/null
+++ b/config/weakref.m4
@@ -0,0 +1,48 @@
+
+dnl Check if the target supports weak.
+AC_DEFUN([GCC_CHECK_ATTRIBUTE_WEAK], [
+ AC_CACHE_CHECK([whether the target supports weak],
+ ac_cv_have_attribute_weak, [
+ weakref_m4_saved_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror"
+ AC_TRY_COMPILE([void __attribute__((weak)) foo(void) { }],
+ [], ac_cv_have_attribute_weak=yes,
+ ac_cv_have_attribute_weak=no)
+ CFLAGS="$weakref_m4_saved_CFLAGS"])
+ if test x"$ac_cv_have_attribute_weak" = xyes; then
+ AC_DEFINE(HAVE_ATTRIBUTE_WEAK, 1,
+ [Define to 1 if the target supports __attribute__((weak)).])
+ fi])
+
+dnl Check whether weak refs work like the ELF ones.
+dnl This means that the weak reference works without having to satify
+dnl linkage for the item.
+dnl There are targets (at least Darwin) where we have fully functional
+dnl weakrefs at runtime, but must supply the referenced item at link time.
+AC_DEFUN([GCC_CHECK_ELF_STYLE_WEAKREF], [
+ AC_CACHE_CHECK([whether weak refs work like ELF],
+ ac_cv_have_elf_style_weakref, [
+ weakref_m4_saved_CFLAGS="$CFLAGS"
+ case "${host}" in
+ *-apple-darwin*) CFLAGS="$CFLAGS -Wl,-undefined,dynamic_lookup" ;;
+ *) ;;
+ esac
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[
+extern void fNotToBeFound(void) __attribute__((weak));
+int main ()
+{
+ if (fNotToBeFound)
+ return 1;
+ else
+ return 0;
+}
+]])], ac_cv_have_elf_style_weakref=yes, ac_cv_have_elf_style_weakref=no, [
+case "${host}" in
+ alpha*-dec-osf*) ac_cv_have_elf_style_weakref=no ;;
+ *-apple-darwin[[89]]*) ac_cv_have_elf_style_weakref=no ;;
+ *) ac_cv_have_elf_style_weakref=yes;;
+esac])CFLAGS="$weakref_m4_saved_CFLAGS"])
+if test x"$ac_cv_have_elf_style_weakref" = xyes; then
+ AC_DEFINE(HAVE_ELF_STYLE_WEAKREF, 1, [Define to 1 if target has a weakref that works like the ELF one.])
+fi])
+
diff --git a/configure b/configure
index f5c76be1968..e68c402db9f 100755
--- a/configure
+++ b/configure
@@ -6833,10 +6833,6 @@ case "${target}" in
extra_arflags_for_target=" -X32_64"
extra_nmflags_for_target=" -B -X32_64"
;;
- *-*-darwin[3-9]*)
- # ranlib before Darwin10 requires the -c flag to look at common symbols.
- extra_ranlibflags_for_target=" -c"
- ;;
esac
alphaieee_frag=/dev/null
diff --git a/configure.ac b/configure.ac
index a5034b26217..7e27de4f57f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2291,10 +2291,6 @@ case "${target}" in
extra_arflags_for_target=" -X32_64"
extra_nmflags_for_target=" -B -X32_64"
;;
- *-*-darwin[[3-9]]*)
- # ranlib before Darwin10 requires the -c flag to look at common symbols.
- extra_ranlibflags_for_target=" -c"
- ;;
esac
alphaieee_frag=/dev/null
diff --git a/contrib/ChangeLog b/contrib/ChangeLog
index b3828975b68..abe317ad9db 100644
--- a/contrib/ChangeLog
+++ b/contrib/ChangeLog
@@ -1,3 +1,7 @@
+2011-11-21 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * make_sunver.pl: Convert '?' in glob patterns to '.'.
+
2011-11-07 Richard Henderson <rth@redhat.com>
Merged from transactional-memory.
diff --git a/contrib/make_sunver.pl b/contrib/make_sunver.pl
index 292837402db..96ad22c2311 100644
--- a/contrib/make_sunver.pl
+++ b/contrib/make_sunver.pl
@@ -276,9 +276,10 @@ while (<F>) {
if (/^([ \t]*)([^ \t;{}#]+);?[ \t]*$/) {
my $ws = $1;
my $ptn = $2;
- # Turn the glob into a regex by replacing '*' with '.*'.
+ # Turn the glob into a regex by replacing '*' with '.*', '?' with '.'.
# Keep $ptn so we can still print the original form.
($pattern = $ptn) =~ s/\*/\.\*/g;
+ $pattern =~ s/\?/\./g;
if ($glob eq 'ign') {
# We're in a local: * section; just continue.
diff --git a/fixincludes/ChangeLog b/fixincludes/ChangeLog
index a73eaacea2f..bbdfc17622a 100644
--- a/fixincludes/ChangeLog
+++ b/fixincludes/ChangeLog
@@ -1,3 +1,9 @@
+2011-11-16 David Edelsohn <dje.gcc@gmail.com>
+
+ * inclhack.def (aix_once_init_[12]): New fixes.
+ * fixincl.x: Regenerate.
+ * tests/base/pthread.h: Update.
+
2011-10-25 Mike Stump <mikestump@comcast.net>
PR target/48851
diff --git a/fixincludes/fixincl.x b/fixincludes/fixincl.x
index 0f5e5fcae8e..dac0a4ed229 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 Sunday October 23, 2011 at 12:18:29 PM EST
+ * It has been AutoGen-ed November 7, 2011 at 01:16:39 PM by AutoGen 5.10
* From the definitions inclhack.def
* and the template file fixincl
*/
-/* DO NOT SVN-MERGE THIS FILE, EITHER Sun Oct 23 12:18:29 EST 2011
+/* DO NOT SVN-MERGE THIS FILE, EITHER Mon Nov 7 13:16:39 EST 2011
*
* You must regenerate it. Use the ./genfixes script.
*
@@ -15,7 +15,7 @@
* certain ANSI-incompatible system header files which are fixed to work
* correctly with ANSI C and placed in a directory that GNU C will search.
*
- * This file contains 220 fixup descriptions.
+ * This file contains 222 fixup descriptions.
*
* See README for more information.
*
@@ -559,6 +559,84 @@ static const char* apzAix_Net_If_ArpPatch[] = {
/* * * * * * * * * * * * * * * * * * * * * * * * * *
*
+ * Description of Aix_Once_Init_1 fix
+ */
+tSCC zAix_Once_Init_1Name[] =
+ "aix_once_init_1";
+
+/*
+ * File name selection pattern
+ */
+tSCC zAix_Once_Init_1List[] =
+ "pthread.h\0";
+/*
+ * Machine/OS name selection pattern
+ */
+tSCC* apzAix_Once_Init_1Machs[] = {
+ "*-*-aix*",
+ (const char*)NULL };
+
+/*
+ * content selection pattern - do fix if pattern found
+ */
+tSCC zAix_Once_Init_1Select0[] =
+ "#define[ \t]PTHREAD_ONCE_INIT \\\\\n\
+\\{ \\\\\n";
+
+#define AIX_ONCE_INIT_1_TEST_CT 1
+static tTestDesc aAix_Once_Init_1Tests[] = {
+ { TT_EGREP, zAix_Once_Init_1Select0, (regex_t*)NULL }, };
+
+/*
+ * Fix Command Arguments for Aix_Once_Init_1
+ */
+static const char* apzAix_Once_Init_1Patch[] = {
+ "format",
+ "#define PTHREAD_ONCE_INIT \\\n\
+{{ \\\n",
+ (char*)NULL };
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * Description of Aix_Once_Init_2 fix
+ */
+tSCC zAix_Once_Init_2Name[] =
+ "aix_once_init_2";
+
+/*
+ * File name selection pattern
+ */
+tSCC zAix_Once_Init_2List[] =
+ "pthread.h\0";
+/*
+ * Machine/OS name selection pattern
+ */
+tSCC* apzAix_Once_Init_2Machs[] = {
+ "*-*-aix*",
+ (const char*)NULL };
+
+/*
+ * content selection pattern - do fix if pattern found
+ */
+tSCC zAix_Once_Init_2Select0[] =
+ "[ \t]0 \\\\\n\
+\\}\n";
+
+#define AIX_ONCE_INIT_2_TEST_CT 1
+static tTestDesc aAix_Once_Init_2Tests[] = {
+ { TT_EGREP, zAix_Once_Init_2Select0, (regex_t*)NULL }, };
+
+/*
+ * Fix Command Arguments for Aix_Once_Init_2
+ */
+static const char* apzAix_Once_Init_2Patch[] = {
+ "format",
+ "\t0 \\\n\
+}}\n",
+ (char*)NULL };
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
* Description of Aix_Pthread fix
*/
tSCC zAix_PthreadName[] =
@@ -8956,9 +9034,9 @@ static const char* apzX11_SprintfPatch[] = {
*
* List of all fixes
*/
-#define REGEX_COUNT 262
+#define REGEX_COUNT 264
#define MACH_LIST_SIZE_LIMIT 181
-#define FIX_COUNT 220
+#define FIX_COUNT 222
/*
* Enumerate the fixes
@@ -8974,6 +9052,8 @@ typedef enum {
AAB_SUN_MEMCPY_FIXIDX,
AIX_COMPLEX_FIXIDX,
AIX_NET_IF_ARP_FIXIDX,
+ AIX_ONCE_INIT_1_FIXIDX,
+ AIX_ONCE_INIT_2_FIXIDX,
AIX_PTHREAD_FIXIDX,
AIX_STDINT_1_FIXIDX,
AIX_STDINT_2_FIXIDX,
@@ -9237,6 +9317,16 @@ tFixDesc fixDescList[ FIX_COUNT ] = {
AIX_NET_IF_ARP_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
aAix_Net_If_ArpTests, apzAix_Net_If_ArpPatch, 0 },
+ { zAix_Once_Init_1Name, zAix_Once_Init_1List,
+ apzAix_Once_Init_1Machs,
+ AIX_ONCE_INIT_1_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
+ aAix_Once_Init_1Tests, apzAix_Once_Init_1Patch, 0 },
+
+ { zAix_Once_Init_2Name, zAix_Once_Init_2List,
+ apzAix_Once_Init_2Machs,
+ AIX_ONCE_INIT_2_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
+ aAix_Once_Init_2Tests, apzAix_Once_Init_2Patch, 0 },
+
{ zAix_PthreadName, zAix_PthreadList,
apzAix_PthreadMachs,
AIX_PTHREAD_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
diff --git a/fixincludes/inclhack.def b/fixincludes/inclhack.def
index 7445d99f00b..0567bf474e0 100644
--- a/fixincludes/inclhack.def
+++ b/fixincludes/inclhack.def
@@ -384,6 +384,35 @@ fix = {
};
/*
+ * pthread.h on AIX defines PTHREAD_ONCE_INIT without enough braces.
+ */
+fix = {
+ hackname = aix_once_init_1;
+ mach = "*-*-aix*";
+ files = "pthread.h";
+ select = "#define[ \t]PTHREAD_ONCE_INIT \\\\\n"
+ "\\{ \\\\\n";
+ c_fix = format;
+ c_fix_arg = "#define PTHREAD_ONCE_INIT \\\n"
+ "{{ \\\n";
+ test_text = "#define PTHREAD_ONCE_INIT \\\\\n"
+ "{ \\\\\n";
+};
+
+fix = {
+ hackname = aix_once_init_2;
+ mach = "*-*-aix*";
+ files = "pthread.h";
+ select = "[ \t]0 \\\\\n"
+ "\\}\n";
+ c_fix = format;
+ c_fix_arg = " 0 \\\n"
+ "}}\n";
+ test_text = " 0 \\\\\n"
+ "}\n";
+};
+
+/*
* pthread.h on AIX 4.3.3 tries to define a macro without whitspace
* which violates a requirement of ISO C.
*/
diff --git a/fixincludes/tests/base/pthread.h b/fixincludes/tests/base/pthread.h
index 834f0519ed2..24a215fa47f 100644
--- a/fixincludes/tests/base/pthread.h
+++ b/fixincludes/tests/base/pthread.h
@@ -9,6 +9,20 @@
+#if defined( AIX_ONCE_INIT_1_CHECK )
+#define PTHREAD_ONCE_INIT \
+{{ \
+
+#endif /* AIX_ONCE_INIT_1_CHECK */
+
+
+#if defined( AIX_ONCE_INIT_2_CHECK )
+ 0 \
+}}
+
+#endif /* AIX_ONCE_INIT_2_CHECK */
+
+
#if defined( AIX_PTHREAD_CHECK )
#define PTHREAD_MUTEX_INITIALIZER \
{...init stuff...}
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9a713cfbf1c..d37a4411fb6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,38 +1,1137 @@
-2011-11-14 Zolotukhin Michael <michael.v.zolotukhin@gmail.com>
+2011-11-28 Georg-Johann Lay <avr@gjlay.de>
+
+ * doc/extend.texi (AVR Built-in Functions): Add documentation for
+ __builtin_avr_map8 and __builtin_avr_map16.
+
+ * config/avr/avr.md: Document new %t and %T asm output codes.
+ (define_c_enum "unspec"): Add UNSPEC_MAP_BITS.
+ (adjust_len): Add map_bits.
+ (map_bitsqi, map_bitshi): New insns.
+ * config/avr/avr-protos.h (avr_out_map_bits): New.
+ * config/avr/avr-protos.c (print_operand): Implement %t and %T.
+ (adjust_insn_length): Handle ADJUST_LEN_MAP_BITS.
+ (avr_double_int_push_digit): New function.
+ (avr_map, avr_revert_map, avr_swap_map, avr_id_map): New functions.
+ (avr_sig_map, avr_map_hamming_byte): New functions.
+ (avr_out_swap_bits, avr_out_revert_bits, avr_move_bits,
+ avr_out_map_bits): New functions.
+ (enum avr_builtin_id): Add AVR_BUILTIN_MAP8, AVR_BUILTIN_MAP16.
+ (avr_init_builtins): Populate __builtin_avr_map8, __builtin_avr_map16.
+ (bdesc_2arg): Add __builtin_avr_map8, __builtin_avr_map16 ...
+ (avr_expand_builtin): ...and expand them.
+ * config/avr/avr-c.c (avr_cpu_cpp_builtins): New built-in defines:
+ __BUILTIN_AVR_MAP8, __BUILTIN_AVR_MAP16.
+
+2011-11-27 Richard Sandiford <rdsandiford@googlemail.com>
+
+ PR target/51278
+ * config/mips/mips.c (mips_rtx_costs): Handle baddu.
+
+2011-11-27 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * config/mips/mips.c (mips16_unextended_reference_p): Test for BLKmode.
+
+2011-11-27 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * config/mips/mips-protos.h (mips_emit_binary): Declare.
+ * config/mips/mips.c (mips_emit_binary): Make global.
+ (mips_set_mips16_mode): Turn off -mfix-r4000 in MIPS16 mode.
+ (mips_conditional_register_usage): Don't treat LO and HI as
+ register operands in MIPS16 mode.
+ (mips_mulsidi3_gen_fn): Use {u,}mulsidi3_{32,64}bit_mips16
+ for MIPS16 code.
+ * config/mips/predicates.md (muldiv_target_operand): New predicate.
+ (move_operand): Allow hilo_operand.
+ * config/mips/mips.md (mul<mode>3): Explicitly specify LO as the
+ target of MIPS16 multiplies, then move it into the target register.
+ (mul<mode>3_internal, *macc2, *msac2): Use muldiv_target_operand.
+ (<u>mulsidi3_32bit_mips16): New expander.
+ (<u>mulsidi3_32bit): Use muldiv_target_operand.
+ (<u>mulsidi3_32bit_r4000): Disable for ISA_HAS_DSP.
+ (<u>mulsidi3_64bit): Require !TARGET_MIPS16. Split into
+ <u>mulsidi3_64bit_split.
+ (<u>mulsidi3_64bit_mips16): New expander.
+ (<u>mulsidi3_64bit_split): Likewise, using expansions from
+ two previous define_splits.
+ (<u>mulsidi3_64bit_hilo, *muls<u>_di, <u>msubsidi4): Use
+ muldiv_target_operand.
+ (<su>mulsi3_highpart): Use <su>mulsi3_highpart_split for MIPS16 code.
+ (<su>mulsi3_highpart_internal): Require !TARGET_MIPS16.
+ Split into <su>mulsi3_highpart_split.
+ (<su>mulsi3_highpart_split): New expander.
+ (<su>muldi3_highpart): Turn into a define_expand.
+ Use <su>muldi3_highpart_split for MIPS16 code.
+ (<su>muldi3_highpart_internal): Renamed from <su>muldi3_highpart.
+ Require !TARGET_MIPS16. Split into <su>muldi3_highpart_split.
+ (<su>muldi3_highpart_split): New expander.
+ (<u>mulditi3): Explicitly specify LO as the target of MIPS16
+ multiplies, then move it into the target register.
+ (<u>mulditi3_internal, <u>maddsidi4): Use muldiv_target_operand.
+ (divmod<mode>4, udivmod<mode>4): Turn into define_expands.
+ Use <u>divmod<mode>4_split for MIPS16 code, then explicitly
+ move LO into operand 0.
+ (divmod<mode>4_internal, udivmod<mode>4_internal): Renamed
+ from <u>divmod<mode>4. Use muldiv_target_operand.
+ Require !TARGET_MIPS16. Split into <u>divmod<mode>4_split.
+ (<u>divmod<mode>4_split): New expander.
+ (<u>divmod<GPR:mode>4_hilo_<HILO:mode>): Use muldiv_target_operand.
+ (mfhi<GPR:mode>_<HILO:mode>): Use hilo_operand.
+
+2011-11-27 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * hard-reg-set.h (target_hard_regs): Add x_accessible_reg_set
+ and x_operand_reg_set.
+ (accessible_reg_set, operand_reg_set): New macros.
+ * reginfo.c (init_reg_sets): Initialize accessible_reg_set and
+ operand_reg_set.
+ (saved_accessible_reg_set, saved_operand_reg_set): New variables.
+ (save_register_info): Save them.
+ (restore_register_info): Restore them.
+ (init_reg_sets_1): Limit operand_reg_set to accessible_reg_set.
+ Remove NO_REGS registers from operand_reg_set. Treat members
+ of operand_reg_set as fixed.
+ * recog.c (general_operand): Check operand_reg_set rather than
+ NO_REGS.
+ (register_operand, nonmemory_operand): Likewise.
+ * varasm.c (make_decl_rtl): Always use DECL_MODE as the mode of
+ register variables. Check accessible_reg_set and operand_reg_set.
+ * config/mips/mips.c (mips_conditional_register_usage): Remove
+ inaccessible register from accessible_reg_set, rather than just
+ making them fixed.
+
+2011-11-27 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * config/pa/pa-linux.h (TARGET_GAS): Remove comment.
+
+2011-11-26 Richard Henderson <rth@redhat.com>
+
+ * config/arm/arm.c (arm_init_libfuncs): Call init_sync_libfuncs
+ for Linux.
+
+2011-11-26 Richard Henderson <rth@redhat.com>
+
+ * optabs.c (expand_atomic_fetch_op): Always return result.
+
+ * optabs.c (init_sync_libfuncs_1): Include max in iteration.
+
+ * omp-low.c (expand_omp_atomic): Assume anything aligned to
+ BIGGEST_ALIGNMENT is aligned.
+
+2011-11-26 Richard Henderson <rth@redhat.com>
+
+ * config/m68k/m68k.md (UNSPECV_CAS_1, UNSPECV_CAS_2): New.
+ (UNSPECV_TAS_1, UNSPECV_TAS_2): New.
+ (I): New mode iterator.
+ (xz): New mode attribute.
+ * config/m68k/sync.md: New file.
+
+ * config/m68k/linux.h (TARGET_INIT_LIBFUNCS): New.
+ * config/m68k/m68k.c (m68k_init_sync_libfuncs): New.
+
+2011-11-26 Nathan Sidwell <nathan@acm.org>
+
+ PR gcov-profile/51297
+ * gcov.c (main): Allocate initial names and sources arrays.
+ (find_source): Don't check for null name or source arrays here.
+
+2011-11-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/49912
+ * cfgrtl.c (rtl_verify_flow_info_1): Ignore also EDGE_PRESERVE bit
+ when counting n_branch.
+
+2011-11-26 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/sync.md (movdi_via_fpu): Add %Z insn suffixes.
+
+2011-11-26 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ PR middle-end/50074
+ * calls.c (mem_overlaps_already_clobbered_arg_p):
+ Return false if no outgoing arguments have been stored so far.
+
+2011-11-25 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/avr/avr.c (print_operand): Support code = 'i' for CONST_INT.
+
+2011-11-24 Andrew MacLeod <amacleod@redhat.com>
+
+ PR other/51011
+ * tree.h (is_builtin_name): No longer external.
+ * builtins.c (is_builtin_name): Make static.
+ * varasm.c (incorporeal_function_p): __sync and __atomic external calls
+ are not incorporeal and may need asm label processing.
+
+2011-11-25 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/50566
+ * config/avr/avr-protos.h (avr_log_t): Add field .builtin.
+ * config/avr/avr-log.c (avr_log_set_avr_log): Initialize it.
+ Don't bypass TARGET_ALL_DEBUG. Print self-info with ?.
+ (avr_log_vadump): Support %D and %X to print double_int.
+ (avr_double_int_pop_digit): New static function.
+ (avr_dump_double_int_hex): New static function.
+
+2011-11-24 Enkovich Ilya <ilya.enkovich@intel.com>
+
+ PR target/51287
+ * config/i386/i386.c (distance_non_agu_define_in_bb): Fix insn
+ attr check.
+
+2011-11-24 Andrew MacLeod <amacleod@redhat.com>
+
+ * optab.c (maybe_emit_atomic_exchange): New. Try to emit an
+ atomic_exchange pattern.
+ (maybe_emit_sync_lock_test_and_set): New. Try to emit an exchange
+ using __sync_lock_test_and_set.
+ (maybe_emit_compare_and_swap_exchange_loop): New. Try to emit an
+ exchange using a compare_and_swap loop.
+ (expand_sync_lock_test_and_set): New. Expand sync_lock_test_and_set.
+ (expand_atomic_test_and_set): New. Expand test_and_set operation.
+ (expand_atomic_exchange): Use new maybe_emit_* functions.
+ (expand_atomic_store): Use new maybe_emit_* functions.
+ * builtins.c (expand_builtin_sync_lock_test_and_set): Call
+ expand_sync_lock_test_and_set routine.
+ (expand_builtin_atomic_exchange): Remove parameter from call.
+ (expand_builtin_atomic_clear): Use atomic_clear pattern if present.
+ (expand_builtin_atomic_test_and_set): Add target and simply call
+ expand_atomic_test_and_set.
+ (expand_builtin): Add target to expand_builtin_atomic_test_and_set.
+ * expr.h (expand_atomic_exchange): Add parameter.
+ (expand_sync_lock_test_and_set): New prototype.
+ (expand_atomic_test_and_set, expand_atomic_clear): New prototypes.
+
+2011-11-24 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/51134
+ * config/i386/i386.h (processor_costs): Revert revision 181357.
+ * config/i386/i386.c (cost models): Likewise.
+ (core_cost): Likewise.
+ (promote_duplicated_reg): Likewise.
+ (promote_duplicated_reg_to_size): Likewise.
+ (processor_target): Likewise.
+ (expand_set_or_movmem_via_loop_with_iter): Likewise.
+ (expand_set_or_movmem_via_loop): Likewise.
+ (emit_strset): Likewise.
+ (expand_movmem_epilogue): Likewise.
+ (expand_setmem_epilogue): Likewise.
+ (expand_movmem_prologue): Likewise.
+ (expand_setmem_prologue): Likewise.
+ (expand_constant_movmem_prologue): Likewise.
+ (expand_constant_setmem_prologue): Likewise.
+ (decide_alg): Likewise.
+ (decide_alignment): Likewise.
+ (ix86_expand_movmem): Likewise.
+ (ix86_expand_setmem): Likewise.
+ (ix86_slow_unaligned_access): Likewise.
+ * config/i386/i386.md (strset): Likewise.
+ * config/i386/sse.md (vec_dupv4si): Likewise.
+ (vec_dupv2di): Likewise.
+
+2011-11-24 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/avr/avr.md (*rotlhi2.15): Set length to 4.
+
+2011-11-24 Razya Ladelsky <razya@il.ibm.com>
+
+ * tree-data-ref.c (initialize_data_dependence_relation): Update
+ comment for the self dependence case.
+ (compute_self_dependence): Remove.
+ * tree-vect-data-refs.c (vect_analyze_data_refs): Remove call to
+ compute_self_dependenc.
+
+2011-11-24 Alan Modra <amodra@gmail.com>
+
+ * c-decl.c (warn_if_shadowing): Don't warn if shadowed
+ identifier is from system header.
+
+2011-11-23 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/51261
+ * config/i386/i386.c (decide_alg): Initialize *dynamic_check
+ even if !optimize.
+
+2011-11-23 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/48455
+ * doc/invoke.texi (-fira-region): Document default values.
+
+ * flags-types.h (enum ira_region): Add new value
+ IRA_REGION_AUTODETECT.
+
+ * common.opt (fira-region): Set up initial value to
+ IRA_REGION_AUTODETECT.
+
+ * toplev.c (process_options): Set up flag_ira_region depending on
+ -O options.
+
+ * ira.c (ira.c): Remove optimize guard for ira_build.
+
+2011-11-23 Chung-Lin Tang <cltang@codesourcery.com>
+
+ PR rtl-optimization/50496
+ * jump.c (redirect_jump): Assert fail on nlabel == NULL_RTX
+ only after epilogue is created. Add comments.
+
+2011-11-22 Richard Henderson <rth@redhat.com>
+
+ * config/ia64/ia64.c (ia64_expand_atomic_op): Add model parameter.
+ Generate the barrier required for the memory model.
+ (rtx_needs_barrier): Handle UNSPEC_FETCHADD_REL, UNSPEC_CMPXCHG_REL.
+ * config/ia64/ia64-protos.h: Update.
+ * config/ia64/ia64.md (UNSPEC_FETCHADD_REL): New.
+ (UNSPEC_CMPXCHG_REL): New.
+ * config/ia64/sync.md (mem_thread_fence): New.
+ (atomic_load<IMODE>, atomic_store<IMODE>): New.
+ (atomic_compare_and_swap<IMODE>): New.
+ (cmpxchg_acq_<I124MODE>, cmpxchg_acq_di): New.
+ (atomic_exchange<IMODE>): New.
+ (xchg_acq_<IMODE>): Rename from sync_lock_test_and_set<IMODE>.
+ (atomic_<FETCHOP><IMODE>, atomic_nand<IMODE>): New.
+ (atomic_fetch_<FETCHOP><IMODE>, atomic_fetch_nand<IMODE>): New.
+ (atomic_<FETCHOP>_fetch<IMODE>, atomic_nand_fetch<IMODE>): New.
+ (fetchadd_rel_<I48MODE>): New.
+ (sync_<FETCHOP><IMODE>, sync_nand<IMODE>): Remove.
+ (sync_old_<FETCHOP><IMODE>, sync_old_nand<IMODE>): Remove.
+ (sync_new_<FETCHOP><IMODE>, sync_new_nand<IMODE>): Remove.
+ (sync_compare_and_swap<IMODE>): Remove.
+ (sync_lock_release<IMODE>): Remove.
+
+ * config/ia64/ia64.md: Use define_c_enum for UNSPEC_*
+ and UNSPECV_* constants.
+
+2011-11-22 Tom de Vries <tom@codesourcery.com>
+
+ PR rtl-optimization/50764
+ * sched-deps.c (sched_analyze_insn): Make sure frame-related insns are
+ not moved past preceding jump.
+
+2011-11-22 Jeff Law <law@redhat.com>
+
+ * doc/contrib.texi: Add entry for David Binderman.
+
+2011-11-22 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * postreload.c (reload_combine): Mark reg_state as invalid at
+ volatile insns if there has been a use already.
+
+2011-11-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * opts.c (finish_options): Do not fail for -fgnu-tm.
+ * gimple-streamer-out.c (output_gimple_stmt): Handle
+ GIMPLE_TRANSACTION.
+ * gimple-streamer-in.c (input_gimple_stmt): Same.
+ * lto-cgraph.c (input_overwrite_node): Read tm_clone bit.
+ (lto_output_node): Write tm_clone bit.
+
+2011-11-22 Ian Lance Taylor <iant@google.com>
+
+ * doc/install.texi (Configuration): Correct doc of
+ --enable-build-poststage1-with-cxx: it is not experimental.
+
+2011-11-22 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/51074
+ * fold-const.c (fold_binary_loc): Fix up VEC_INTERLEAVE_*_EXPR
+ handling for BYTES_BIG_ENDIAN.
+ * optabs.c (can_vec_perm_for_code_p): Likewise.
+
+2011-11-22 Michael Matz <matz@suse.de>
+
+ PR other/51125
+ * trans-mem.c (expand_block_tm): Ignore clobbers.
+
+2011-11-22 Iain Sandoe <iains@gcc.gnu.org>
+
+ * config/darwin.h (ENDFILE_SPEC): New.
+ (DARWIN_CRT1_SPEC): Add crttms.o.
+ (STARTFILE_SPEC): Likewise for dynamic libs and bundles.
+ * config/i386.h (ENDFILE_SPEC): Amend to include crttme.o.
+
+2011-11-22 Michael Matz <matz@suse.de>
+
+ PR c++/51264
+ * tree.c (iterative_hash_expr): Remove break after return.
+
+2011-11-22 Iain Sandoe <iains@gcc.gnu.org>
+
+ * target.def (tm_clone_table_section): New hook.
+ * doc/tm.texi.in (TARGET_ASM_TM_CLONE_TABLE_SECTION): Define.
+ * doc/tm.texi: Regenerate.
+ * varasm.c (dump_tm_clone_pairs): Use target tm_clone_table_section.
+ * output.h (default_clone_table_section): New prototype.
+ * config/darwin.h (TARGET_ASM_TM_CLONE_TABLE_SECTION): New.
+ * config/darwin-protos.h (darwin_tm_clone_table_section): New prototype.
+ * config/darwin.c (darwin_tm_clone_table_section): New.
+
+2011-11-21 Torvald Riegel <triegel@redhat.com>
+
+ * trans-mem.c (diagnose_tm_1): Print an expression instead of a
+ declaration in error messages for indirect calls.
+
+2011-11-21 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.c (sparc_regmode_natural_size): New function
+ implementing REGMODE_NATURAL_SIZE taking into consideration vector
+ modes.
+ (sparc_modes_tieable_p): Similarly for MODES_TIEABLE_P.
+ * config/sparc/sparc-protos.h (sparc_regmode_natural_size,
+ sparc_modes_tieable_p): Declare.
+ * gcc/config/sparc/sparc.h (REGMODE_NATURAL_SIZE,
+ MODES_TIEABLE_P): Use new helper functions.
+
+ Revert
+ 2011-11-16 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ PR middle-end/50325
+ * expmed.c (store_bit_field_1): Use extract_bit_field on big
+ endian targets if the source cannot be exactly covered by word
+ mode chunks.
+
+2011-11-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/50827
+ * var-tracking.c (loc_cmp): For ENTRY_VALUEs use ENTRY_VALUE_EXP
+ macro instead of XEXP.
+
+2011-11-21 Andreas Tobler <andreast@fgznet.ch>
+
+ * configure: Regenerate.
+
+2011-11-21 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/avr/avr.c (output_reload_in_const): Loading a byte with 0
+ must not affect cc0.
+ * config/avr/avr.md (*movhi, *movpsi, *movsi, *movsf): Zero to any
+ register does not change cc0. Same for any constant to ld-register.
+
+2011-11-21 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/mmx.md (unspec) <UNSPEC_MOVNTQ, UNSPEC_PFRCP,
+ UNSPEC_PFRCPIT1, UNSPEC_PFRCPIT2, UNSPEC_PFRSQRT, UNSPEC_PFRSQIT1>:
+ Move from config/i386/i386.md
+ (unspecv) <UNSPECV_EMMS, UNSPECV_FEMMS>: Ditto.
+ * config/i386/sse.md (unspec) <UNSPEC_MOVNT,UNSPEC_MOVU, UNSPEC_LDDQU,
+ UNSPEC_PSHUFB, UNSPEC_PSIGN, UNSPEC_PALIGNR, UNSPEC_EXTRQI,
+ UNSPEC_EXTRQ, UNSPEC_INSERTQI, UNSPEC_INSERTQ, UNSPEC_BLENDV,
+ UNSPEC_INSERTPS, UNSPEC_DP, UNSPEC_MOVNTDQA, UNSPEC_MPSADBW,
+ UNSPEC_PHMINPOSUW, UNSPEC_PTEST, UNSPEC_PCMPESTR, UNSPEC_PCMPISTR,
+ UNSPEC_FMADDSUB, UNSPEC_XOP_UNSIGNED_CMP, UNSPEC_XOP_TRUEFALSE,
+ UNSPEC_XOP_PERMUTE, UNSPEC_FRCZ, UNSPEC_AESENC, UNSPEC_AESENCLAST,
+ UNSPEC_AESDEC, UNSPEC_AESDECLAST, UNSPEC_AESIMC,
+ UNSPEC_AESKEYGENASSIST, UNSPEC_PCLMUL, UNSPEC_PCMP, UNSPEC_VPERMIL,
+ UNSPEC_VPERMIL2, UNSPEC_VPERMIL2F128, UNSPEC_CAST, UNSPEC_VTESTP,
+ UNSPEC_VCVTPH2PS, UNSPEC_VCVTPS2PH, UNSPEC_VPERMSI, UNSPEC_VPERMDF,
+ UNSPEC_VPERMSF, UNSPEC_VPERMTI, UNSPEC_GATHER, UNSPEC_VSIBADDR>: Ditto.
+ (unspecv) <UNSPECV_LDMXCSR, UNSPECV_STMXCSR, UNSPECV_CLFLUSH,
+ UNSPECV_MONITOR, UNSPECV_MWAIT, UNSPECV_VZEROALL, UNSPECV_VZEROUPPER>:
+ Ditto.
+ * config/i386/sync.md (unspec) <UNSPEC_LFENCE, UNSPEC_SFENCE,
+ UNSPEC_MFENCE, UNSPEC_MOVA>: Ditto.
+ (unspecv) <UNSPECV_CMPXCHG_1, UNSPECV_CMPXCHG_2, UNSPECV_CMPXCHG_3,
+ UNSPECV_CMPXCHG_4, UNSPECV_XCHG, UNSPECV_LOCK>: Ditto.
+ (sse2_lfence): Move from config/i386/sse.md.
+ (*sse2_lfence): Ditto.
+ (sse_sfence): Ditto.
+ (*sse_sfence): Ditto.
+ (sse2_mfence): Ditto.
+ (mfence_sse2): Ditto. Rename from *sse2_mfence. Enable also
+ for TARGET_64BIT.
+ (mem_thread_fence): Use mfence_sse2.
+
+2011-11-21 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/avr/avr.h (struct base_arch_s): Add field sfr_offset.
+ * config/avr/avr-devices.c: Ditto. And initialize it.
+ * config/avr/avr-c.c (avr_cpu_cpp_builtins): New built-in define
+ __AVR_SFR_OFFSET__.
+ * config/avr/avr-protos.h (out_movqi_r_mr, out_movqi_mr_r): Remove.
+ (out_movhi_r_mr, out_movhi_mr_r): Remove.
+ (out_movsi_r_mr, out_movsi_mr_r): Remove.
+ * config/avr/avr.md (*cbi, *sbi): Use %i instead of %m-0x20.
+ (*insv.io, *insv.not.io): Ditto.
+ * config/avr/avr.c (out_movsi_r_mr, out_movsi_mr_r): Make static.
+ (print_operand): Implement "%i" to print address as I/O address.
+ (output_movqi): Clean up call of out_movqi_mr_r.
+ (output_movhi): Clean up call of out_movhi_mr_r.
+ (avr_file_start): Use avr_current_arch->sfr_offset instead of
+ magic -0x20. Use TMP_REGNO, ZERO_REGNO instead of 0, 1.
+ (avr_out_sbxx_branch): Use %i instead of %m-0x20.
+ (out_movqi_r_mr, out_movqi_mr_r): Ditto. And make static.
+ (out_movhi_r_mr, out_movhi_mr_r): Ditto. And use avr_asm_len.
+ (out_shift_with_cnt): Clean up code: Use avr_asm_len.
+ (output_movsisf): Use output_reload_insisf for all CONSTANT_P sources.
+ (avr_out_movpsi): USE avr_out_reload_inpsi for all CONSTANT_P sources.
+ Clean up call of avr_out_store_psi.
+ (output_reload_in_const): Don't cut symbols longer than 2 bytes.
+ (output_reload_insisf): Filter CONST_INT_P or CONST_DOUBLE_P to
+ try if setting pre-cleared register is advantageous.
+ (avr_out_plus_1): Use gen_int_mode instead of GEN_INT.
+
+2011-11-20 Joey Ye <joey.ye@arm.com>
+
+ * expr.c (expand_expr_real_1): Correctly handle strict volatile
+ bitfield loads smaller than mode size.
+
+2011-11-20 Richard Henderson <rth@redhat.com>
+
+ * config/mips/mips.c (mips_init_libfuncs): Call init_sync_libfuncs.
+
+2011-11-20 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/51235
+ * config/i386/i386.c (ix86_expand_vcond): Generate TARGET_XOP
+ patterns for supported mode only.
+
+ PR target/51236
+ * config/i386/i386.c (ix86_expand_builtin)
+ <IX86_BUILTIN_GATHERALTSIV4DI>: Use CODE_FOR_avx2_gathersiv4di.
+
+2011-11-20 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (UNSPEC_MOVNTI): Remove.
+ (UNSPEC_MOVNTQ): New unspec.
+ * config/i386/mmx.md (sse_movntq): Rename from sse_movntdi.
+ Use UNSPEC_MOVNTQ instead of UNSPEC_MOVNT.
+ * config/i386/sse.md (sse2_movnti<mode>): Use UNSPEC_MOVNT instead of
+ UNSPEC_MOVNTI.
+ (STORENT_MODE): Add DI and V4DI modes.
+
+2011-11-20 Nathan Sidwell <nathan@acm.org>
+
+ PR gcov-profile/51113
+ * coverage.c (build_var): Propagate visibility for public
+ decls. Use make_decl_one_only for PIC correctness.
+
+ testsuite/
+ * gcc.misc-tests/gcov-13.c: Check gcovpart-13b coverage
+ * gcc.misc-tests/gcov-16.c: New.
+ * gcc.misc-tests/gcov-17.c: New.
+ * g++.dg/gcov/gcov-8.C: New.
+ * g++.dg/gcov/gcov-9.C: New.
+ * g++.dg/gcov/gcov-10.C: New.
+
+2011-11-19 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR rtl-optimization/51187
+ * reorg.c (relax_delay_slots): Do not consider a jump useless if there
+ is a barrier between the jump and its target label.
+
+2011-11-19 Patrick Marlier <patrick.marlier@gmail.com>
+
+ PR middle-end/51211
+ * tracer.c (ignore_bb_p): Don't copy GIMPLE_TRANSACTION.
+
+2011-11-19 Eric Botcazou <ebotcazou@adacore.com>
+
+ * expmed.c (store_bit_field_1): Revert bogus formatting change.
+
+2011-11-19 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/50493
+ * config/arm/arm.c (neon_disambiguate_copy): Correctly handle partial
+ overlap of src and dest operands.
+
+2011-11-19 Iain Sandoe <iains@gcc.gnu.org>
+
+ * config/darwin.h (ASM_DEBUG_SPEC): New.
+ * config/darwin9.h (ASM_DEBUG_SPEC): New.
+
+2011-11-18 Jan Hubicka <jh@suse.cz>
+
+ * config/i386/i386.c (atom_cost): Disable SSE loop until alignment
+ issues are fixed.
+
+2011-11-18 Anatoly Sokolov <aesok@post.ru>
+
+ * config/cris/cris.c (cris_function_value_regno_p): Make static.
+ (TARGET_FUNCTION_VALUE_REGNO_P): Define.
+ * config/cris/cris.h (FUNCTION_VALUE_REGNO_P): Remove.
+ * config/cris/cris-protos.h (cris_function_value_regno_p): Remove.
+
+2011-11-18 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/33944
+ * doc/extend.texi: Document __builtin_ia32_movnti64.
+
+ * config/i386/emmintrin.h (_mm_stream_si64): New.
+
+ * config/i386/i386-builtin-types.def: Add VOID_FTYPE_PLONGLONG_LONGLONG.
+
+ * config/i386/i386.c (ix86_builtins): Add IX86_BUILTIN_MOVNTI64.
+ (bdesc_special_args): Update __builtin_ia32_movnti. Add
+ __builtin_ia32_movnti64.
+ (ix86_expand_special_args_builtin): Handle
+ VOID_FTYPE_PLONGLONG_LONGLONG.
+
+ * config/i386/i386.md (UNSPEC_MOVNTI): New.
+
+ * config/i386/sse.md (sse2_movntsi): Renamed to ...
+ (sse2_movnti<mode>): This.
+
+2011-11-18 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/49868
+ * config/avr/avr.h (base_arch_s): Add field n_segments.
+ (ADDR_SPACE_PGM1, ADDR_SPACE_PGM2, ADDR_SPACE_PGM3,
+ ADDR_SPACE_PGM4, ADDR_SPACE_PGM5, ADDR_SPACE_PGMX): New address spaces.
+ (AVR_HAVE_ELPM, AVR_HAVE_ELPMX): New defines.
+ (INIT_EXPANDERS): New define.
+ * config/avr/avr-protos.h (avr_mem_pgmx_p): New.
+ (avr_init_expanders): New.
+ (avr_emit_movmemhi, avr_out_movmem): New.
+ (avr_xload_libgcc_p): New.
+ * config/avr/avr-c.c (avr_register_target_pragmas): Register
+ address spaces __pgm1, __pgm2, __pgm3, __pgm4 __pgm5, __pgmx.
+ (avr_cpu_cpp_builtins): Add built-in defines __PGM1,
+ __PGM2, __PGM3, __PGM4, __PGM5, __PGMX.
+ * config/avr/avr-devices.c (avr_arch_types): Set field n_segments.
+
+ * config/avr/avr.c (AVR_SECTION_PROGMEM): Change define to cover
+ 3 bits instead of just 1.
+ (xstring_empty, xstring_e, rampz_rtx): New static GTYed variables.
+ (progmem_section): Change from section to array of sections.
+ (progmem_section_prefix): New static variable.
+ (avr_file_start): Print set for __RAMPZ__
+ (avr_option_override): Move initialization of RTXes from here...
+ (avr_init_expanders): ...to this new function.
+ (avr_pgm_segment): New static function.
+ (avr_decl_pgm_p): Handle error_mark_node.
+ (avr_mem_pgmx_p, avr_decl_pgmx_p): New static functions.
+ (avr_out_xload, avr_find_unused_d_reg): New static functions.
+ (expand_prologue, expand_epilogue): Use rampz_rtx.
+ (print_operand): Hande CONST_STRING.
+ (avr_xload_libgcc_p): New static function.
+ (avr_out_lpm_no_lpmx, avr_out_lpm): Handle ELPM.
+ (avr_progmem_p): Return 2 for 24-bit flash address space.
+ (avr_out_sbxx_branch): Clean-up code from ASn macros.
+ (out_movqi_r_mr, out_movqi_mr_r): Ditto. And recognize RAMPZ's
+ address and print symbolically.
+ (avr_asm_named_section, avr_section_type_flags,
+ avr_encode_section_info, avr_asm_select_section,
+ avr_addr_space_address_mode, avr_addr_space_pointer_mode,
+ avr_addr_space_legitimate_address_p, avr_addr_space_convert,
+ avr_addr_space_legitimize_address): Handle new address spaces.
+ (avr_output_progmem_section_asm_op): New static function.
+ (avr_asm_init_sections): Initialize progmem_section[].
+ (adjust_insn_length): Handle ADJUST_LEN_XLOAD, ADJUST_LEN_MOVMEM.
+ (avr_const_address_lo16): New static function.
+ (avr_assemble_integer): Use it to handle 3-byte integers.
+ (avr_emit_movmemhi, avr_out_movmem): New functions.
+
+ * config/avr/predicates.md (nox_general_operand): Handle new
+ address spaces.
+ * config/avr/avr.md (unspec): Add UNSPEC_MOVMEM.
+ (adjust_len): Add xload, movmem.
+ (SP_ADDR): New define_constants.
+ (isa): Add "lpm", "lpmx", "elpm", "elpmx".
+ (enabled): Handle them.
+ (load<mode>_libgcc): New expander.
+ (*load.<mode>.libgcc): Rename to load_<mode>_libgcc.
+ (xload8_A, xload<mode>_A): New insn-and-splits.
+ (xload_8, xload_<mode>_libgcc, xload_<mode>, loadmem_elpm): New insns.
+ (mov<mode>): Handle new address spaces.
+ (movmemhi): Rewrite using avr_emit_movmemhi.
+ (MOVMEM_r_d): New mode attribute.
+ (movmem_<mode>, movmem_qi_elpm): New insns.
+ (setmemhi, *clrmemqi, *clrmemhi, strlenhi, *strlenhi): Unquote
+ C-code. Use label instead of hard-coded instrunction lengths.
+
+2011-11-18 Martin Jambor <mjambor@suse.cz>
+
+ PR tree-optimization/50605
+ * gimple.c (is_gimple_ip_invariant_address): Also handle MEM_REFs
+ of IPA invariant decls.
+
+2011-11-18 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * tree-outof-ssa.c (insert_back_edge_copies): Add call to
+ mark_dfs_back_edges.
+
+2011-11-18 Iain Sandoe <iains@gcc.gnu.org>
+
+ PR target/49992
+ * configure.ac: Remove ranlib special-casing for Darwin.
+ * configure: Regenerate.
+
+2011-11-18 Uros Bizjak <ubizjak@gmail.com>
+
+ PR tree-optimization/51118
+ * fold-const.c (fold_checksum_tree): Check for TS_TYPED structure
+ before using TREE_TYPE accessor on expr.
+
+2011-11-17 Jan Hubicka <jh@suse.cz>
+
+ PR bootstrap/51134
+ * i386.c (atom_cost): Fix 32bit memset description.
+ (expand_set_or_movmem_via_loop_with_iter): Output proper bounds check
+ for epilogue loops.
+ (expand_movmem_epilogue): Handle epilogues up to size 15 w/o producing
+ byte loop.
+ (decide_alg): sse_loop is not useable wthen SSE2 is disabled;
+ when not optimizing always use rep movsb or lincall; do not produce
+ word sized loops when optimizing memset for size (to avoid need
+ for large constants).
+ (ix86_expand_movmem): Get into sync with ix86_expand_setmem;
+ choose unroll factors better; always do 128bit moves when producing
+ SSE loops; do not produce loopy epilogue when size is too small.
+ (promote_duplicated_reg_to_size): Do not look into desired alignments
+ when doing vector expansion.
+ (ix86_expand_setmem): Track better when promoted value is available;
+ choose unroll factors more sanely. Output loopy epilogue only
+ when needed.
+
+2011-11-17 Steve Ellcey <sje@cup.hp.com>
+
+ PR middle-end/51144
+ * output.h (fprint_w): Remove.
+ * final.c (fprint_w): Remove.
+ (output_addr_const): Change fprint_w back to fprintf.
+
+2011-11-17 Andrew Pinski <apinski@cavium.com>
+
+ * config/host-linux.c (TRY_EMPTY_VM_SPACE): Define for MIPS.
+
+2011-11-17 Andrew MacLeod <amacleod@redhat.com>
+
+ * builtins.c (expand_builtin): Remove 4th parameter representing
+ weak/strong mode when __atomic_compare_exchange becomes a library call.
+
+2011-11-17 Richard Henderson <rth@redhat.com>
+
+ * config/rs6000/rs6000.c (rs6000_expand_atomic_compare_and_swap): Get
+ new pseudo for target after convert_modes.
+ (rs6000_expand_atomic_exchange, rs6000_expand_atomic_op): Likewise.
+
+2011-11-17 Richard Henderson <rth@redhat.com>
+
+ * builtins.c (expand_builtin_mem_thread_fence): Remove.
+ (expand_builtin_mem_signal_fence): Remove.
+ (expand_builtin_atomic_thread_fence): Use expand_mem_thread_fence.
+ (expand_builtin_sync_synchronize): Likewise.
+ (expand_builtin_atomic_signal_fence): Use expand_mem_signal_fence.
+ * optabs.c (expand_asm_memory_barrier): Split out from
+ expand_builtin_mem_signal_fence.
+ (expand_mem_thread_fence): New, a combination of code from
+ expand_builtin_mem_thread_fence and expand_builtin_sync_synchronize.
+ (expand_mem_signal_fence): Moved and renamed from
+ expand_builtin_mem_signal_fence.
+ (expand_atomic_exchange): Use expand_mem_thread_fence.
+ (expand_atomic_load, expand_atomic_store): Likewise.
+ * expr.h, optabs.h: Update decls.
+
+2011-11-17 Bin Cheng <bin.cheng@arm.com>
+
+ PR rtl-optimization/50663
+ * cprop.c (implicit_set_indexes): New global variable.
+ (insert_set_in_table): Add additional parameter and record implicit
+ set information.
+ (hash_scan_set): Add additional parameter and pass it to above.
+ (hash_scan_insn): Pass false to hash_scan_set.
+ (compute_hash_table_work): Pass true to hash_scan_set.
+ (compute_cprop_data): Add implicit set to AVIN of block which the
+ implicit set is recorded for.
+ (one_cprop_pass): Handle implicit_set_indexes array.
+
+2011-11-17 Michael Matz <matz@suse.de>
+
+ PR middle-end/50644
+ PR middle-end/50741
+ * tree-ssa-live.c (mark_all_vars_used_1): Recurse only for decls of
+ current function.
+ (remove_unused_locals): Ditto.
+
+2011-11-16 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (alpha_split_compare_and_swap_12): Copy
+ ALIAS_SET_MEMORY_BARRIER when creating a new memory.
+ (alpha_split_atomic_exchange_12): Likewise.
+ * config/rs6000/rs6000.c (rs6000_adjust_atomic_subword): Likewise.
+
+2011-11-16 Joseph Myers <joseph@codesourcery.com>
+
+ * config/i386/i386elf.h (PREFERRED_DEBUGGING_TYPE): Remove.
+
+2011-11-16 David Edelsohn <dje.gcc@gmail.com>
+
+ * config/rs6000/rs6000.c (rs6000_xcoff_section_type_flags):
+ Default to minimum alignment if decl is NULL.
+
+2011-11-16 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/sse.md (round<mode>2_vec_pack_sfix): Optimize V2DFmode
+ sequence for AVX.
+ (<sse4_1>_round<ssemodesuffix>_vec_pack_sfix<avxsizesuffix>): Ditto.
+
+2011-11-16 Venkataramanan Kumar <venkataramanan.kumar@amd.com>
+
+ * doc/invoke.texi: Document AMD bdver1 and btver1.
+
+2011-11-16 Richard Earnshaw <rearnsha@arm.com>
+ Bernd Schmidt <bernds@coudesourcery.com>
+ Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ PR target/49641
+ * config/arm/arm.c (store_multiple_sequence): Avoid cases where
+ the base reg is stored iff compiling for Thumb1.
+
+2011-11-16 Razya Ladelsky <razya@il.ibm.com>
+
+ PR tree-optimization/49960
+ * tree-data-ref.c (initialize_data_dependence_relation): Add
+ initializations.
+ Remove call to compute_self_dependence.
+ (compute_affine_dependence): Remove the !DDR_SELF_REFERENCE condition.
+ (compute_self_dependence): Remove old code. Add call to
+ compute_affine_dependence.
+ (compute_all_dependences): Remove call to compute_self_dependence.
+ Add call to compute_affine_dependence.
+
+2011-11-16 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ PR middle-end/50325
+ * expmed.c (store_bit_field_1): Use extract_bit_field on big
+ endian targets if the source cannot be exactly covered by word
+ mode chunks.
+
+2011-11-15 Joseph Myers <joseph@codesourcery.com>
+
+ * config/i386/i386elf.h (ASM_OUTPUT_ASCII): Change STRING_LIMIT to
+ ELF_STRING_LIMIT.
+
+2011-11-15 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (alpha_pre_atomic_barrier): New.
+ (alpha_post_atomic_barrier): New.
+ (alpha_split_atomic_op): New memmodel argument; honor it.
+ (alpha_split_compare_and_swap): Take array of operands. Honor
+ memmodel; always set bool output
+ (alpha_expand_compare_and_swap_12): Similarly.
+ (alpha_split_compare_and_swap_12): Similarly.
+ (alpha_split_atomic_exchange): Similarly. Rename from
+ alpha_split_lock_test_and_set.
+ (alpha_expand_atomic_exchange_12): Similarly. Rename from
+ alpha_expand_lock_test_and_set_12.
+ (alpha_split_atomic_exchange_12): Similarly. Rename from
+ alpha_split_lock_test_and_set_12.
+ * config/alpha/alpha-protos.h: Update.
+ * config/alpha/alpha.md (UNSPECV_CMPXCHG): New.
+ * config/alpha/constraints.md ("w"): New.
+ * config/alpha/predicates.md (mem_noofs_operand): New.
+ * config/alpha/sync.md (atomic_compare_and_swap<mode>): Rename from
+ sync_compare_and_swap<mode>; add the new parameters.
+ (atomic_exchange<mode>): Update from sync_test_and_set<mode>.
+ (atomic_fetch_<op><mode>): Update from sync_old_<op><mode>.
+ (atomic_<op>_fetch<mode>): Update from sync_new_<op><mode>.
+ (atomic_<op><mode>): Update from sync_<op><mode>.
+
+2011-11-16 Tom de Vries <tom@codesourcery.com>
+
+ * tree-ssa-tail-merge.c (replace_block_by): Add frequency of bb2 to bb1.
+
+2011-11-16 Alan Modra <amodra@gmail.com>
+
+ PR rtl-optimization/51051
+ PR bootstrap/51086
+ * function.c (thread_prologue_and_epilogue_insns): Guard
+ emitting return with single_succ_p test.
+
+2011-11-15 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/epiphany/epiphany.md (mov<mode>cc): Fix code to
+ get mode from CMP_OP1 if CMP_OP0 is VOIDmode.
+
+2011-11-15 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/sse.md (vec_pack_trunc_v2df): Optimize sequence for AVX.
+ (vec_pack_sfix_trunc_v2df): Ditto.
+ (vec_pack_sfix_v2df): Ditto.
+ (vec_pack_sfix_trunc_v4df): Generate fix_truncv4dfv4si2 and
+ avx_vec_concatv8si patterns.
+ (vec_pack_sfix_v4df): Generate avx_cvtpd2dq256 and
+ avx_vec_concatv8si patterns.
+
+2011-11-15 Torvald Riegel <triegel@redhat.com>
+
+ * c-parser.c (c_parser_transaction_expression): Require parentheses
+ when parsing transaction expressions.
+
+2011-11-15 Tristan Gingold <gingold@adacore.com>
+
+ * incpath.c (get_added_cpp_dirs): New function.
+ * incpath.h (get_added_cpp_dirs): Declare.
+ * config/vms/vms-c.c (vms_c_register_includes): New function.
+ (vms_std_modules): New variable.
+ * config/vms/vms.h (TARGET_EXTRA_INCLUDES): Define.
+ (vms_c_register_includes): Declare.
+
+2011-11-15 Tristan Gingold <gingold@adacore.com>
+
+ * c-family/c-pragma.h (pragma_extern_prefix): Declare.
+ * c-family/c-pragma.c (pragma_extern_prefix): Make it public.
+ * config/vms/vms-c.c (saved_extern_prefix): New variable.
+ (vms_pragma_extern_prefix): New function.
+ (vms_c_register_pragma): Register vms_pragma_extern_prefix.
+
+2011-11-15 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/49868
+ * config/avr/avr.h (ADDR_SPACE_PGM): New address spaces.
+ (REGISTER_TARGET_PRAGMAS): New define.
+ * config/avr/avr-protos.h (avr_mem_pgm_p): New.
+ (avr_load_libgcc_p): New.
+ (avr_register_target_pragmas): New.
+ (asm_output_external_libcall): Remove.
+ (avr_log_t): Add field "progmem". Order alphabetically.
+ * config/avr/avr-log.c (avr_log_set_avr_log): Set avr_log.progmem.
+ * config/avr/avr-c.c (langhooks.h): New include.
+ (avr_register_target_pragmas): New function. Register address
+ space __pgm.
+ (avr_cpu_cpp_builtins): Add built-in define __PGM.
+
+ * config/avr/avr.c: Include "c-family/c-common.h".
+ (TARGET_LEGITIMATE_ADDRESS_P): Remove define.
+ (TARGET_LEGITIMIZE_ADDRESS): Remove define.
+ (TARGET_ADDR_SPACE_SUBSET_P): Define to...
+ (avr_addr_space_subset_p): ...this new static function.
+ (TARGET_ADDR_SPACE_CONVERT): Define to...
+ (avr_addr_space_convert): ...this new static function.
+ (TARGET_ADDR_SPACE_ADDRESS_MODE): Define to...
+ (avr_addr_space_address_mode): ...this new static function.
+ (TARGET_ADDR_SPACE_POINTER_MODE): Define to...
+ (avr_addr_space_pointer_mode): ...this new static function.
+ (TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P): Define to...
+ (avr_addr_space_legitimate_address_p): ...this new static function.
+ (TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS): Define to...
+ (avr_addr_space_legitimize_address): ...this new static function.
+ (avr_mode_code_base_reg_class): Handle address spaces.
+ (avr_regno_mode_code_ok_for_base_p): Ditto.
+ (lpm_addr_reg_rtx, lpm_reg_rtx, all_regs_rtx): New static variables.
+ (avr_option_override): Initialize them.
+ (output_reload_in_const): Use all_regs_rtx. Fix signedness of loop
+ variables.
+ (avr_pgm_segment): New static function.
+ (avr_decl_pgm_p, avr_mem_pgm_p): New static functions.
+ (avr_out_lpm, avr_out_lpm_no_lpmx): New static functions.
+ (output_movqi, output_movhi, output_movsisf, avr_out_movpsi): Call
+ avr_out_lpm to handle loads from progmem.
+ (avr_load_libgcc_p): New static function.
+ (avr_progmem_p): Test if decl is in flash.
+ (avr_pgm_pointer_const_p): New static function.
+ (avr_nonconst_pointer_addrspace): New static function.
+ (avr_pgm_check_var_decl): New static function.
+ (avr_insert_attributes): Use it. Change error message to report
+ cause (progmem or address space) when code wants to write to flash.
+ (avr_section_type_flags): Unset section flag SECTION_BSS for
+ data in progmem.
+
+ * config/avr/predicates.md (nop_general_operand): New predicate.
+ (nox_general_operand): New predicate.
+ * config/avr/avr.md (LPM_REGNO): New define_constant.
+ (load<mode>_libgcc): New expander.
+ (*load.<mode>.libgcc): New insn.
+ (mov<mode>): Handle loads from non-generic AS.
+ (movmemhi): Ditto. Propagate address space information to newly
+ created MEM.
+ (movqi_insn, *movhi, *movpsi, *movsi, *movsf): Change predicate #1
+ to nox_general_operand.
+ (ashrqi3, ashrhi3, ashrsi3): Change predicate #1 to
+ nop_general_operand.
+ (ashlqi3, *ashlqi3, ashlhi3, ashlsi3): Ditto.
+ (lshrqi3, *lshrqi3, lshrhi3, lshrsi3): Ditto.
+ (split-lpmx): New split.
+ (*ashlhi3_const, *ashlsi3_const, *ashrhi3_const, *ashrsi3_const,
+ *lshrhi3_const, *lshrsi3_const): Indent, unquote C.
+
+2011-11-15 Maxim Kuvyrkov <maxim@codesourcery.com>
+
+ * ipa-cp.c (ipa_value_from_jfunc): Make global.
+ (ipa_cst_from_jfunc): Remove, use ipa_value_from_jfunc instead.
+ (get_indirect_edge_target): Rename, make global.
+ (devirtualization_time_bonus, estimate_local_effects,)
+ (ipcp_discover_new_direct_edges): Update.
+ * ipa-inline-analysis.c (evaluate_conditions_for_edge):
+ Generalize to also handle types. Rename to ...
+ (evaluate_properties_for_edge): Use instead of
+ evaluate_conditions_for_edge.
+ (estimate_edge_devirt_benefit): New function.
+ (estimate_calls_size_and_time): Use it.
+ (estimate_node_size_and_time, estimate_ipcp_clone_size_and_time,)
+ (inline_merge_summary): Update.
+ (do_estimate_edge_time, do_estimate_edge_growth): Update. Calculate
+ parameter information at the call site and pass it on to subroutines.
+ * tree-inline.c (estimate_num_insns): Distinguish between direct and
+ indirect calls.
+ (init_inline_once): Set size and time costs or indirect calls.
+ * tree-inline.h (eni_weights): Add indirect_call_cost.
+
+2011-11-15 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/51005
+ * tree-ssa-tail-merge.c (delete_basic_block_same_succ): Rename to
+ mark_basic_block_deleted.
+ (update_worklist): Inline purge_bbs.
+ (purge_bbs, unlink_virtual_phi, update_vuses, vop_at_entry)
+ (delete_block_update_dominator_info): Remove.
+ (replace_block_by): Remove update_vops parameter. Partially evaluate
+ for update_vops == false.
+ (apply_clusters): Remove update_vops parameter. Remove update_vops
+ argument in replace_block_by call.
+ (update_debug_stmts): Remove MAY_HAVE_DEBUG_STMTS test.
+ (tail_merge_optimize): Remove update_vops argument to apply_clusters.
+ Remove call to purge_bbs. Add calls to calculate_dominance_info and
+ free_dominance_info. Add MAY_HAVE_DEBUG_STMTS before calling
+ update_debug_stmts. Mark vop var for renaming, if necessary.
+
+2011-11-15 Bernd Schmidt <bernds@codesourcery.com>
+
+ PR rtl-optimization/51051
+ * cfgrtl.c (cfg_layout_can_merge_blocks_p): Return FALSE if the
+ move would cause fallthrough into the exit block.
+
+2011-11-14 Richard Henderson <rth@redhat.com>
+
+ * config/rs6000/rs6000.c (emit_load_locked): Assert the mode is
+ handled.
+ (emit_store_conditional): Likewise.
+ (rs6000_pre_atomic_barrier, rs6000_post_atomic_barrier): New.
+ (rs6000_adjust_atomic_subword): New.
+ (rs6000_mask_atomic_subword, rs6000_finish_atomic_subword): New.
+ (rs6000_expand_atomic_op): Rename from rs6000_emit_sync; rewrite
+ for pre-reload expansion.
+ (rs6000_split_compare_and_swap, rs6000_split_compare_and_swapqhi,
+ rs6000_expand_compare_and_swapqhi): Merge into ...
+ (rs6000_expand_atomic_compare_and_swap): ... here. New function.
+ rs6000_split_lock_test_and_set; expand immediately. Handle
+ QImode and HImode.
+ * config/rs6000/rs6000.md (UNSPEC_LWSYNC): Move and rename
+ from UNSPECV_LWSYNC.
+ * config/rs6000/sync.md (fetchopsi_constr, fetchopdi_constr): Remove.
+ (mem_thread_fence): New.
+ (hwsync): Rename from memory_barrier.
+ (*hwsync): Rename from *sync_internal.
+ (lwsync, *lwsync): Mirror hwsync implementation.
+ (isync): Don't reference memory.
+ (loadsync): New.
+ (atomic_load<INT>, atomic_store<INT>): New.
+ (ATOMIC): New mode iterator.
+ (load_locked<ATOMIC>): Rename from load_locked_<GPR>.
+ (store_conditional<ATOMIC>): Rename from store_conditional_<GPR>.
+ (sync_compare_and_swap<GPR>): Remove.
+ (sync_compare_and_swaphi, sync_compare_and_swapqi): Remove.
+ (sync_compare_and_swapqhi_internal): Remove.
+ (sync_lock_test_and_set<GPR>): Remove.
+ (sync_<FETCHOP><INT1>): Remove.
+ (*sync_<FETCHOP>si_internal, *sync_<FETCHOP>di_internal): Remove.
+ (sync_nand<INT1>, *sync_nand<GPR>_internal): Remove.
+ (sync_old_<FETCHOP><GPR>): Remove.
+ (*sync_old_<FETCHOP>si_internal): Remove.
+ (*sync_old_<FETCHOP>di_internal): Remove.
+ (sync_old_nand<INT1>): Remove.
+ (*sync_old_nand<GPR>_internal): Remove.
+ (sync_new_<FETCHOP><GPR>): Remove.
+ (*sync_new_<FETCHOP>si_internal): Remove.
+ (*sync_new_<FETCHOP>di_internal): Remove.
+ (sync_new_nand<INT1>): Remove.
+ (*sync_new_nand<GPR>_internal): Remove.
+ (*atomic_andsi, *atomic_anddi): Remove.
+ (*sync_addshort_internal, *sync_subshort_internal): Remove.
+ (*sync_andsi_internal, *sync_boolsi_internal): Remove.
+ (*sync_boolcshort_internal): Remove.
+ (sync_lock_release<INT1>): Remove.
+ (atomic_compare_and_swap<INT1>): New.
+ (atomic_exchange<INT1>): New.
+ (atomic_<FETCHOP><INT1>, atomic_nand<INT1>): New.
+ (atomic_fetch_<FETCHOP><INT1>, atomic_fetch_nand<INT1>): New.
+ (atomic_<FETCHOP>_fetch<INT1>, atomic_nand_fetch<INT1>): New.
+
+2011-11-14 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/sse.md (round<mode>2): Use register_operand for
+ operand 1 predicate.
+ (round<mode>2_sfix): Ditto.
+ (round<mode>2_vec_pack_sfix): Ditto for operand 1 and operand 2.
+
+2011-11-14 Nathan Sidwell <nathan@acm.org>
+
+ * gcov.c (canonicalize_name): Protect use of S_ISLNK.
+
+2011-11-14 Jan Hubicka <jh@suse.cz>
+
+ PR target/51126
+ * config/i386/i386.c (core cost model): Correct pasto.
+
+2011-11-14 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/sse.md (round<mode>2_sfix): New expander.
+ (round<mode>2_vec_pack_sfix): Ditto.
+ (<sse4_1>_round<ssemodesuffix>_sfix<avxsizesuffix>): Ditto.
+ (<sse4_1>_round<ssemodesuffix>_vec_pack_sfix<avxsizesuffix>): Ditto.
+ * config/i386/builtin-types.def (V4SI_FTYPE_V4SF_ROUND,
+ V8SI_FTYPE_V8SF_ROUND, V4SI_FTYPE_V2DF_V2DF_ROUND,
+ V8SI_FTYPE_V4DF_V4DF_ROUND): New builtin types.
+ * config/i386/i386.c (ix86_builtins): Add
+ IX86_BUILTIN_{FLOORPD,CEILPD,ROUNDPD_AZ}_VEC_PACK_SFIX{,256} and
+ IX86_BUILTIN_{FLOORPS,CEILPS,ROUNDPS_AZ}_SFIX{,256} defines.
+ (bdesc_args): Add __builtin_ia32_{floorpd,ceilpd}_vec_pack_sfix{,256},
+ __builtin_ia32_roundpd_az_vec_pack_sfix{,256},
+ __builtin_ia32_{floorps,ceilps}_sfix{,256}and
+ __builtin_ia32_roundps_az_sfix{,256} descriptions.
+ (ix86_expand_sse_round_vec_pack_sfix): New.
+ (ix86_expand_args_builtin): Handle V4SI_FTYPE_V4SF_ROUND,
+ V8SI_FTYPE_V8SF_ROUND, V4SI_FTYPE_V2DF_V2DF_ROUND and
+ V8SI_FTYPE_V4DF_V4DF_ROUND types. Check last argument of
+ CODE_FOR_sse4_1_roundpd_vec_pack_sfix, CODE_FOR_sse4_1_roundps_sfix,
+ CODE_FOR_avx_roundpd_vec_pack_sfix256 and CODE_FOR_avx_roundps_sfix256.
+ (ix86_builtin_vectorized_function): Handle
+ BUILT_IN_{I,L,LL}FLOOR{,F}, BUILT_IN_{I,L,LL}CEIL{,F} and
+ BUILT_IN_{I,L,LL}ROUND{,F}
+
+2011-11-14 Jan Hubicka <jh@suse.cz>
+
+ PR middle-end/50598
+ * cgraph.h (varpool_externally_visible_p): Declare.
+ (varpool_add_new_variable): Declare.
+ * tree-emultls.c (get_emutls_init_templ_addr,
+ new_emutls_decl): Use varpool_add_new_variable.
+ * ipa.c (varpool_externally_visible_p): Export.
+ * varpool.c (varpool_add_new_variable): New function.
+
+2011-11-14 Michael Zolotukhin <michael.v.zolotukhin@gmail.com>
Jan Hubicka <jh@suse.cz>
- * config/i386/i386.h (processor_costs): Add second dimension to
- stringop_algs array.
- * config/i386/i386.c (cost models): Initialize second dimension of
- stringop_algs arrays.
+ * config/i386/i386.h (processor_costs): Add second dimension to
+ stringop_algs array.
+ * config/i386/i386.c (cost models): Initialize second dimension of
+ stringop_algs arrays.
(core_cost): New costs based on generic64 costs with updated stringop
values.
- (promote_duplicated_reg): Add support for vector modes, add
- declaration.
- (promote_duplicated_reg_to_size): Likewise.
+ (promote_duplicated_reg): Add support for vector modes, add
+ declaration.
+ (promote_duplicated_reg_to_size): Likewise.
(processor_target): Set core costs for core variants.
- (expand_set_or_movmem_via_loop_with_iter): New function.
- (expand_set_or_movmem_via_loop): Enable reuse of the same iters in
- different loops, produced by this function.
- (emit_strset): New function.
- (expand_movmem_epilogue): Add epilogue generation for bigger sizes,
- use SSE-moves where possible.
- (expand_setmem_epilogue): Likewise.
- (expand_movmem_prologue): Likewise for prologue.
- (expand_setmem_prologue): Likewise.
- (expand_constant_movmem_prologue): Likewise.
- (expand_constant_setmem_prologue): Likewise.
- (decide_alg): Add new argument align_unknown. Fix algorithm of
- strategy selection if TARGET_INLINE_ALL_STRINGOPS is set; Skip sse_loop
- (decide_alignment): Update desired alignment according to chosen move
- mode.
- (ix86_expand_movmem): Change unrolled_loop strategy to use SSE-moves.
- (ix86_expand_setmem): Likewise.
- (ix86_slow_unaligned_access): Implementation of new hook
- slow_unaligned_access.
- * config/i386/i386.md (strset): Enable half-SSE moves.
- * config/i386/sse.md (vec_dupv4si): Add expand for vec_dupv4si.
- (vec_dupv2di): Add expand for vec_dupv2di.
+ (expand_set_or_movmem_via_loop_with_iter): New function.
+ (expand_set_or_movmem_via_loop): Enable reuse of the same iters in
+ different loops, produced by this function.
+ (emit_strset): New function.
+ (expand_movmem_epilogue): Add epilogue generation for bigger sizes,
+ use SSE-moves where possible.
+ (expand_setmem_epilogue): Likewise.
+ (expand_movmem_prologue): Likewise for prologue.
+ (expand_setmem_prologue): Likewise.
+ (expand_constant_movmem_prologue): Likewise.
+ (expand_constant_setmem_prologue): Likewise.
+ (decide_alg): Add new argument align_unknown. Fix algorithm of
+ strategy selection if TARGET_INLINE_ALL_STRINGOPS is set; Skip sse_loop
+ (decide_alignment): Update desired alignment according to chosen move
+ mode.
+ (ix86_expand_movmem): Change unrolled_loop strategy to use SSE-moves.
+ (ix86_expand_setmem): Likewise.
+ (ix86_slow_unaligned_access): Implementation of new hook
+ slow_unaligned_access.
+ * config/i386/i386.md (strset): Enable half-SSE moves.
+ * config/i386/sse.md (vec_dupv4si): Add expand for vec_dupv4si.
+ (vec_dupv2di): Add expand for vec_dupv2di.
2011-11-14 Dimitrios Apostolou <jimis@gmx.net>
@@ -43,8 +1142,7 @@
2011-11-14 Kai Tietz <ktietz@redhat.com>
- * gcov.c (generate_results): Add missing semicolon and
- correct indent.
+ * gcov.c (generate_results): Add missing semicolon and correct indent.
2011-11-14 Ira Rosen <ira.rosen@linaro.org>
@@ -61,9 +1159,8 @@
PR target/50694
* config/sh/sh.h (IS_LITTLE_ENDIAN_OPTION, UNSUPPORTED_SH2A):
New macros.
- (DRIVER_SELF_SPECS): Use new macros to filter out
- unsupported options taking the default configuration into
- account.
+ (DRIVER_SELF_SPECS): Use new macros to filter out unsupported options
+ taking the default configuration into account.
2011-11-13 Jonathan Wakely <jwakely.gcc@gmail.com>
@@ -100,7 +1197,7 @@
2011-11-12 Richard Henderson <rth@redhat.com>
- * config/rs6000/rs6000.md (fix_trunc<SFDF>si2_stfiwx): Use
+ * config/rs6000/rs6000.md (fix_trunc<SFDF>si2_stfiwx): Use
nonimmediate_operand for the destination.
(fixuns_trunc<SFDF>si2_stfiwx): Likewise.
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 89ee407b8f1..24a16bebbcf 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20111114
+20111128
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index f8d6489ac83..77fd4bf15d1 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,11 +1,765 @@
+2011-11-24 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * s-taprop-tru64.adb (Create_Task): Use Unrestricted_Access.
+
+2011-11-23 Thomas Quinot <quinot@adacore.com>
+
+ * thread.c, s-oscons-tmplt.c: Generate __gnat_pthread_condattr_setup
+ only on platforms where this is required, as determined by
+ s-oscons.h.
+
+2011-11-23 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch9.adb: No check on entry index if error on index.
+
+2011-11-23 Gary Dismukes <dismukes@adacore.com>
+
+ * sem_ch6.adb (Analyze_Return_Statement): Improve error messages for
+ return statements nested inside an extended_return_statement.
+ * gcc-interface/Make-lang.in: Update dependencies.
+ * gcc-interface/Makefile.in (MISCLIB): Add -lutil for BSD targets.
+
+2011-11-23 Ed Schonberg <schonberg@adacore.com>
+
+ * freeze.adb (Freeze_All_Ent): An incomplete type is not
+ frozen by a subprogram body that does not come from source.
+
+2011-11-23 Pascal Obry <obry@adacore.com>
+
+ * s-oscons-tmplt.c: Add PTY_Library constant. It contains
+ the library for pseudo terminal support.
+ * g-exptty.ads: Add pseudo-terminal library into a Linker_Options
+ pragma.
+
+2011-11-23 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch9.adb: No check on entry family index if generic.
+
+2011-11-23 Thomas Quinot <quinot@adacore.com>
+
+ * sem_ch9.adb, s-taprop.ads, s-taprop-hpux-dce.adb, s-taprop-irix.adb,
+ s-taprop-posix.adb, s-taprop-rtx.adb, s-taprop-solaris.adb,
+ s-taprop-tru64.adb, s-taprop-vxworks.adb: Move dependency on
+ System.OS_Constants from shared spec of
+ System.Tasking.Primitive_Operations to the specific body variants
+ that really require this dependency.
+
+2011-11-23 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch8.adb (Analyze_Subprogram_Renaming_Declaration):
+ If the declaration has aspects, analyze them so they can be
+ properly rejected.
+
+2011-11-23 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * a-comutr.adb, a-coorma.adb, a-coorse.adb, a-convec.adb, a-cihase.adb,
+ a-cimutr.adb, a-coinve.adb, a-ciorma.adb, a-ciorse.adb, a-cobove.adb,
+ a-cohama.adb, a-cihama.adb, a-cidlli.adb, a-cdlili.adb, a-cbhama.adb,
+ a-cbhase.adb, a-cbmutr.adb, a-cborma.adb, a-cborse.adb, a-cbdlli.adb:
+ Add with and use clause for Ada.Finalization. Type
+ Iterator and Child_Iterator are now derived from Limited_Controlled.
+ (Finalize): New routine.
+ (Iterate): Add a renaming of counter Busy and
+ increment it. Update the return aggregate.
+ (Iterate_Children): Add a renaming of
+ counter Busy and increment it. Update the return aggregate.
+ (Iterate_Subtree): Add a renaming of counter Busy and increment
+ it. Update the return aggregate.
+ * a-cdlili.ads, a-cidlli.ads: Type List_Access is now a general access
+ type.
+ * a-cihama.ads: Type Map_Access is now a general access type.
+ * a-comutr.ads, a-cimutr.ads: Use type Natural for the two locks
+ associated with the tree.
+ * a-cohama.ads: Type Map_Access is now a general access type.
+ * a-coinve.ads, a-convec.ads: Type Vector_Access is now a general
+ access type.
+ * exp_ch5.adb (Expand_Iterator_Loop): Do not create a block
+ to wrap the loop as this is done at an earlier step, during
+ analysis. The declarations of the iterator and the cursor use
+ the usual Insert_Action mechanism when added into the tree.
+ * sem_ch5.adb (Analyze_Loop_Statement): Remove local constant
+ Loop_Statement and replace all respective uses by N. Add local
+ constant Loc. Preanalyze the loop iterator to discover whether
+ it is a container iterator and if it is, wrap the loop in a
+ block. This ensures that any controlled temporaries produced
+ by the iteration scheme share the same lifetime of the loop.
+ (Is_Container_Iterator): New routine.
+ (Is_Wrapped_In_Block): New routine.
+ (Pre_Analyze_Range): Move spec and body to the library level.
+
+2011-11-23 Sergey Rybin <rybin@adacore.com frybin>
+
+ * gnat_ugn.texi, vms_data.ads: Add documentation for new gnatpp option
+ that controls casing of type and subtype names.
+
+2011-11-23 Yannick Moy <moy@adacore.com>
+
+ * sem_ch3.adb: Minor addition of comments.
+
+2011-11-23 Thomas Quinot <quinot@adacore.com>
+
+ * prj-part.adb (Extension_Withs): New global variable,
+ contains the head of the list of WITH clauses from the EXTENDS
+ ALL projects for which virtual packages are being created.
+ (Look_For_Virtual_Projects_For): When recursing through
+ an EXTENDS ALL, add the WITH clauses of the extending
+ project to Extension_Withs. When adding a project to the
+ Virtual_Hash, record the associated Extension_Withs list.
+ (Create_Virtual_Extending_Project): Add a copy of the appropriate
+ Extension_Withs to the virtual project.
+
+2011-11-23 Thomas Quinot <quinot@adacore.com>
+
+ * mlib-tgt-specific-vxworks.adb: Minor reformatting.
+
+2011-11-23 Thomas Quinot <quinot@adacore.com>
+
+ * Make-generated.in (Sdefault.Target_Name): Set to
+ $(target_noncanonical) instead of $(target) for consistency.
+
+2011-11-23 Matthew Heaney <heaney@adacore.com>
+
+ * a-cdlili.adb, a-cidlli.adb, a-cbdlli.adb (Iterator): Declared
+ Iterator type as limited (First, Last): Cursor return value
+ depends on iterator node value (Iterate): Use start position as
+ iterator node value (Next, Previous): Forward to corresponding
+ cursor-based operation.
+
+2011-11-23 Matthew Heaney <heaney@adacore.com>
+
+ * a-coorse.ads, a-ciorse.ads, a-cborse.ads (Set_Iterator_Interfaces):
+ Renamed from Ordered_Set_Iterator_Interfaces.
+ * a-coorse.adb, a-ciorse.adb, a-cborse.adb (Iterator): Declared
+ Iterator type as limited (First, Last): Cursor return value
+ depends on iterator node value (Iterate): Use start position as
+ iterator node value (Next, Previous): Forward to corresponding
+ cursor-based operation.
+ * a-cohase.ads, a-cohase.adb: Implemented forward iterator.
+ * a-cihase.adb, a-cbhase.adb (Iterator): Removed unnecessary
+ node component (First, Next): Forward call to corresponding
+ cursor-based operation (Iterate): Representation of iterator no
+ longer has node component
+
+2011-11-23 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_intr.adb (Expand_Unc_Deallocation): Ensure that the
+ dereference has a proper type before the side effect removal
+ mechanism kicks in.
+ * sem_ch3.adb (Analyze_Subtype_Declaration): Handle a rare case
+ where the base type of the subtype is a private itype created
+ to act as the partial view of a constrained record type. This
+ scenario manifests with equivalent class-wide types for records
+ with unknown discriminants.
+
+2011-11-23 Jerome Guitton <guitton@adacore.com>
+
+ * s-osprim-vxworks.adb (Clock): Use Clock_RT_Ada.
+
+2011-11-23 Thomas Quinot <quinot@adacore.com>
+
+ * s-oscons-tmplt.c: Fix unbalanced preprocessor directives Minor
+ reformatting/reorganization.
+
+2011-11-23 Thomas Quinot <quinot@adacore.com>
+
+ * g-htable.ads: Remove old comments.
+
+2011-11-23 Thomas Quinot <quinot@adacore.com>
+
+ * exp_imgv.adb: Minor reformatting.
+
+2011-11-23 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch9.adb (Analyze_Entry_Declaration): Check for entry
+ family bounds out of range.
+
+2011-11-23 Matthew Heaney <heaney@adacore.com>
+
+ * a-cohama.adb, a-cihama.adb, a-cbhama.adb (Iterator): Declare
+ type as limited, and remove node component.
+ (First, Next): Forward call to corresponding cursor-based operation.
+ (Iterate): Representation of iterator no longer has node component.
+
+2011-11-23 Yannick Moy <moy@adacore.com>
+
+ * exp_util.adb: Revert previous change to remove side-effects in Alfa
+ mode, which is not the correct thing to do for renamings.
+
+2011-11-23 Thomas Quinot <quinot@adacore.com>
+
+ * s-osinte-hpux.ads, s-taprop-vxworks.adb, s-taprop-tru64.adb,
+ s-osinte-vxworks.ads, s-osinte-aix.ads, s-osinte-lynxos.ads,
+ s-osinte-solaris-posix.ads, s-taprop-solaris.adb, a-exetim-posix.adb,
+ s-osinte-irix.ads, s-osinte-solaris.ads, s-oscons-tmplt.c,
+ s-taprop-irix.adb, s-osinte-hpux-dce.ads, Makefile.rtl,
+ s-osinte-tru64.ads, s-osinte-darwin.ads, s-taprop.ads,
+ s-osinte-freebsd.ads, s-osinte-lynxos-3.ads, s-taprop-hpux-dce.adb,
+ s-taprop-posix.adb: Remove hard-coded clock ids;
+ instead, generate them in System.OS_Constants.
+ (System.OS_Constants.CLOCK_RT_Ada): New constant denoting the
+ id of the clock providing Ada.Real_Time.Monotonic_Clock.
+ * thread.c: New file.
+ (__gnat_pthread_condattr_setup): New function. For platforms where
+ CLOCK_RT_Ada is not CLOCK_REALTIME, set appropriate condition
+ variable attribute.
+
+2011-11-23 Yannick Moy <moy@adacore.com>
+
+ * sem_ch3.adb: Restore the use of Expander_Active instead of
+ Full_Expander_Active, so that the evaluation is forced in Alfa
+ mode too. Otherwise, we end up with an unexpected insertion in a
+ place where it is not supposed to happen, on default parameters
+ of a call.
+
+2011-11-23 Thomas Quinot <quinot@adacore.com>
+
+ * prj-pp.adb, prj-pp.ads: Minor new addition: wrapper procedure "wpr"
+ for Pretty_Print, for use from within gdb.
+
+2011-11-23 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_ch5.adb (Expand_Iterator_Loop): Wrap the expanded loop
+ and the cursor declarations in a block, so that the loop variable
+ is local to the construct.
+
+2011-11-23 Matthew Heaney <heaney@adacore.com>
+
+ * a-coorma.ads, a-ciorma.ads, a-cborma.ads (Iterate): Returns
+ type Reversible_Iterator'Class.
+ * a-coorma.adb, a-ciorma.adb, a-cborma.adb (Iterator):
+ Declare type as limited.
+ (First, Last): Return value depends on iterator's start node value.
+ (Next, Previous): Call corresponding Cursor-based operation.
+ (Iterate): Indicate whether complete or partial iteration
+
+2011-11-23 Robert Dewar <dewar@adacore.com>
+
+ * errout.adb: Minor reformattin (Finalize): Take templates into
+ account for warning suppression.
+ * errout.ads (Set_Specific_Warning_Off): Add Used parameter.
+ * erroutc.adb: Minor reformatting (Finalize): Take generic
+ templates into account for warning suppress.
+ * erroutc.ads (Set_Specific_Warning_Off): Add Used parameter.
+ * sem_prag.adb: Minor reformatting (Analyze_Pragma,
+ case Warnings): Provide Used parameter in call to
+ Set_Specific_Warnings_Off (to deal with generic template case).
+
+2011-11-23 Pascal Obry <obry@adacore.com>
+
+ * sem_prag.adb (Process_Convention): Better error message for
+ stdcall convention on dispatching calls.
+
+2011-11-23 Gary Dismukes <dismukes@adacore.com>
+
+ * sem_ch4.adb, sem_ch13.adb: Minor reformatting.
+
+2011-11-23 Javier Miranda <miranda@adacore.com>
+
+ * exp_ch6.adb (Expand_Simple_Function_Return): Add missing
+ implicit type conversion when the returned object is allocated
+ in the secondary stack and the type of the returned object is
+ an interface. Done to force generation of displacement of the
+ "this" pointer.
+
+2011-11-23 Pascal Obry <obry@adacore.com>
+
+ * impunit.adb: Add g-exptty and g-tty units.
+
+2011-11-23 Robert Dewar <dewar@adacore.com>
+
+ * exp_imgv.adb: Minor code reorganization (use Make_Temporary).
+
+2011-11-23 Robert Dewar <dewar@adacore.com>
+
+ * exp_util.adb, par-ch6.adb, sem_res.adb, par-util.adb: Minor
+ reformatting.
+
+2011-11-23 Yannick Moy <moy@adacore.com>
+
+ * sem_ch13.adb (Analyze_Aspect_Specifications): Place error on
+ line of precondition/ postcondition/invariant.
+
+2011-11-23 Pascal Obry <obry@adacore.com>
+
+ * g-exptty.ads, g-exptty.adb, g-tty.ads, g-tty.adb,
+ terminals.c: New files.
+ Makefile.rtl: Add these new files.
+ * gnat_rm.texi: Add documentation for GNAT.Expect.TTY.
+ * gcc-interface/Makefile.in: Add g-exptty, g-tty, terminals.o
+ * gcc-interface/Make-lang.in: Update dependencies.
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * exp_imgv.adb (Expand_Width_Attribute): Handle case of Discard_Names.
+ * sem_attr.adb (Eval_Attribute, case Width): Ditto.
+
+2011-11-21 Thomas Quinot <quinot@adacore.com>
+
+ * sinfo.ads: Minor reformatting.
+
+2011-11-21 Yannick Moy <moy@adacore.com>
+
+ * exp_util.adb: Minor reformatting. Update comments.
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * exp_prag.adb, exp_util.adb, sinfo.ads, sem_res.adb, s-stposu.adb,
+ sem_attr.adb, s-stposu.ads, s-taprop-solaris.adb, s-taprop-irix.adb,
+ sem_ch6.adb: Minor reformatting.
+
+2011-11-21 Arnaud Charlet <charlet@adacore.com>
+
+ * s-taprop-irix.adb, s-taprop-solaris.adb (Create_Task): Use
+ Unrestricted_Access to deal with fact that we properly detect the
+ error if Access is used.
+ * gcc-interface/Make-lang.in: Update dependencies.
+
+2011-11-21 Yannick Moy <moy@adacore.com>
+
+ * exp_prag.adb (Expand_Pragma_Check): Place error on first character
+ of expression.
+ * sem_res.adb (Resolve_Short_Circuit): Place error on first
+ character of expression.
+
+2011-11-21 Yannick Moy <moy@adacore.com>
+
+ * exp_util.adb (Remove_Side_Effects): Do nothing in Alfa mode.
+
+2011-11-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_attr.adb (Expand_N_Attribute_Reference, case
+ Max_Size_In_Storage_Elements): Account for the size of the
+ hidden list header which precedes controlled objects allocated
+ on the heap.
+ * rtsfind.ads: Add RE_Header_Size_With_Padding to the runtime
+ tables.
+ * sinfo.adb (Header_Size_Added): New routine.
+ (Set_Header_Size_Added): New routine.
+ * sinfo.ads: Add flag Controlled_Header_Added along with
+ associated comment.
+ (Header_Size_Added): New inlined routine.
+ (Set_Header_Size_Added): New inlined routine.
+ * s-stposu.adb (Allocate_Any_Controlled): Use
+ Header_Size_With_Padding to calculate the proper
+ size of the header.
+ (Deallocate_Any_Controlled): Use
+ Header_Size_With_Padding to calculate the proper size
+ of the header. (Header_Size_With_Padding): New routine.
+ (Nearest_Multiple_Rounded_Up): Removed along with its uses.
+ * s-stposu.ads (Header_Size_With_Padding): New routine.
+
+2011-11-21 Ed Schonberg <schonberg@adacore.com>
+
+ * aspects.adb: Aspect specifications are allowed on renaming
+ declarations
+ * par-ch6.adb (P_Subprogram): Parse aspect specifications in a
+ subprogram renaming declaration
+
+2011-11-21 Tristan Gingold <gingold@adacore.com>
+
+ * env.c: Remove unused declaration.
+
+2011-11-21 Pascal Obry <obry@adacore.com>
+
+ * s-os_lib.ads: Minor style fix.
+
+2011-11-21 Pascal Obry <obry@adacore.com>
+
+ * adaint.c (__gnat_dup2): When fd are stdout, stdin or stderr and
+ identical, do nothing on Windows XP.
+
+2011-11-21 Yannick Moy <moy@adacore.com>
+
+ * sem_ch3.adb (Constrain_Index, Process_Range_Expr_In_Decl):
+ Use Full_Expander_Active instead of Expander_Active to control
+ the forced evaluation of expressions for the sake of generating
+ checks.
+
+2011-11-21 Thomas Quinot <quinot@adacore.com>
+
+ * init.c: On FreeBSD, stack checking failures may raise SIGBUS.
+
+2011-11-21 Tristan Gingold <gingold@adacore.com>
+
+ * sysdep.c (mode_read_text, mode_write_text, mode_append_text,
+ mode_read_binary, mode_write_binary, mode_append_binary,
+ mode_read_text_plus, mode_write_text_plus, mode_append_text_plus,
+ mode_read_binary_plus, mode_write_binary_plus,
+ mode_append_binary_plus): Remove unused declarations.
+
+2011-11-21 Yannick Moy <moy@adacore.com>
+
+ * gnat_rm.texi: Minor rewording.
+
+2011-11-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_imgv.adb (Expand_Width_Attribute): Emit
+ an error message rather than a warning when pragma Discard_Names
+ prevents the computation of 'Width. Do not emit an error through
+ the use of RE_Null.
+
+2011-11-21 Javier Miranda <miranda@adacore.com>
+
+ * exp_ch6.adb (Make_Build_In_Place_Call_In_Allocator): Add
+ implicit type conversion when the type of the allocator is an
+ interface. Done to force generation of displacement of the "this"
+ pointer when required.
+
+2011-11-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sinfo.ads, sinfo.adb: Corresponding_Spec applies to expression
+ functions, and is set when the expression is a completion of a
+ previous declaration.
+ * sem_ch6.adb (Analyze_Expression_Function): To determine properly
+ whether an expression function completes a previous declaration,
+ use Find_Corresponding_Spec, as when analyzing a subprogram body.
+
+2011-11-21 Steve Baird <baird@adacore.com>
+
+ * sem_util.adb (Deepest_Type_Access_Level): Improve comment.
+ (Type_Access_Level): Improve comment.
+
+2011-11-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/Makefile.in (INCLUDES_FOR_SUBDIR): Add $(fsrcdir) by
+ means of -iquote unconditionally.
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch3.adb, sem_util.adb, sem_res.adb, sem_attr.adb: Minor
+ reformatting.
+
+2011-11-21 Arnaud Charlet <charlet@adacore.com>
+
+ * s-taprop-posix.adb (Create_Task): Use Unrestricted_Access
+ to deal with fact that we properly detect the error if Access
+ is used.
+
+2011-11-21 Steve Baird <baird@adacore.com>
+
+ * sem_util.ads: Update comment describing function
+ Deepest_Access_Level.
+ * sem_util.adb (Deepest_Type_Access_Level): Return Int'Last for a
+ generic formal type.
+ (Type_Access_Level): Return library level
+ for a generic formal type.
+ * sem_attr.adb (Resolve_Attribute): Replace two Type_Access_Level
+ calls with calls to Deepest_Type_Access_Level.
+ * sem_ch3.adb (Analyze_Component_Declaration): replace a
+ Type_Access_Level call with a call to Deepest_Type_Access_Level.
+ * sem_res.adb (Resolve_Allocator.Check_Allocator_Discrim_Accessibility):
+ Replace three Type_Access_Level calls with calls to
+ Deepest_Type_Access_Level.
+ (Resolve_Allocator): Replace a Type_Access_Level call with a call to
+ Deepest_Type_Access_Level.
+ (Valid_Conversion.Valid_Array_Conversion): Replace a
+ Type_Access_Level call with a call to Deepest_Type_Access_Level.
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch3.adb, s-taprop-vms.adb, opt.ads: Minor reformatting.
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * sinput.ads: Minor comment fix.
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * exp_attr.adb (Expand_N_Attribute_Reference, case First_Bit,
+ Last_Bit, Position): Handle 2005 case.
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * s-atocou-builtin.adb (Decrement): Use Unrestricted_Access
+ to deal with fact that we properly detect the error if Access
+ is used.
+ (Increment): Same fix.
+ * s-taprop-linux.adb (Create_Task): Use Unrestricted_Access
+ to deal with fact that we properly detect the error if Access
+ is used.
+ * sem_util.adb (Is_Volatile_Object): Properly record that A.B is
+ volatile if the B component is volatile. This affects the check
+ for passing such a by reference volatile actual to a non-volatile
+ formal (which should be illegal)
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * freeze.adb (Freeze_Enumeration_Type): Make sure to set both
+ size and alignment for foreign convention enumeration types.
+ * layout.adb (Set_Elem_Alignment): Redo setting of alignment
+ when size is set.
+
+2011-11-21 Yannick Moy <moy@adacore.com>
+
+ * checks.adb (Apply_Access_Check, Apply_Arithmetic_Overflow_Check,
+ Apply_Discriminant_Check, Apply_Divide_Check,
+ Apply_Selected_Length_Checks, Apply_Selected_Range_Checks,
+ Build_Discriminant_Checks, Insert_Range_Checks, Selected_Length_Checks,
+ Selected_Range_Checks): Replace reference to Expander_Active
+ with reference to Full_Expander_Active, so that expansion of
+ checks is not performed in Alfa mode
+
+2011-11-21 Tristan Gingold <gingold@adacore.com>
+
+ * s-taprop-vms.adb (Create_Task): Use Unrestricted_Access to deal with
+ fact that we properly detect the error if Access is used.
+
+2011-11-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * par-ch4.adb (P_Quantified_Expression): Add an Ada 2012 check.
+
+2011-11-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_imgv.adb: Add with and use clause for Errout.
+ (Expand_Width_Attribute): Emit a warning when in
+ configurable run-time mode to provide a better diagnostic message.
+
+2011-11-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * s-finmas.adb (Finalize): Add comment concerning double finalization.
+
+2011-11-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch3.adb (Access_Definition): If the access definition
+ is itself the return type of an access to function definition
+ which is ultimately the return type of an access to subprogram
+ declaration, its scope is the enclosing scope of the ultimate
+ access to subprogram.
+
+2011-11-21 Steve Baird <baird@adacore.com>
+
+ * sem_res.adb (Valid_Conversion): If a conversion was legal
+ in the body of a generic, then the corresponding conversion is
+ legal in the expanded body of an instance of the generic.
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch3.adb: Minor reformatting.
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * s-utf_32.adb (Is_UTF_32_Line_Terminator): Recognize NEL as
+ line terminator.
+ * sinput.ads: Add section on Handling of Source Line Terminators.
+ * types.ads (Line_Terminator): Adjust comments.
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * frontend.adb (Frontend): Capture restrictions from config files
+ * lib-load.adb (Load_Unit): Save/set/restore restriction pragma
+ information
+ * lib-xref.adb (Generate_Reference): Fix handling of obsolescent
+ references. This was noticed during debugging, but it is not
+ known if it causes real bugs.
+ * restrict.ads, restrict.adb: New routines to save/set/restore
+ non-partition-wide restrictions.
+ * s-rident.ads: Comment changes for new handling of
+ No_Elaboration_Code
+ * sem.adb (Sem): Save/Set/Restore non-partition-wide restrictions
+ * sem_ch10.adb (Analyze_Compilation_Unit): Remove incomplete
+ attempt to save/restore non-partition-wide restrictions (now
+ this work is all done in Sem).
+ * sem_prag.adb (Process_Restrictions_Or_Restriction_Warnings):
+ Special handling for restriction No_Elaboration_Code.
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * gnat_ugn.texi: Document new handling of restrictions pragmas.
+
+2011-11-21 Pascal Obry <obry@adacore.com>
+
+ * s-taprop-linux.adb (Initialize_Lock): Do not allocate a cond
+ attribute as not needed.
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * sem_prag.adb: Minor reformatting.
+
+2011-11-21 Pascal Obry <obry@adacore.com>
+
+ * gnat_rm.texi: Document restriction for stdcall convention on
+ dispatching calls.
+
+2011-11-21 Pascal Obry <obry@adacore.com>
+
+ * sem_prag.adb (Process_Convention): A dispatching call cannot
+ have a stdcall calling convention.
+
+2011-11-21 Pascal Obry <obry@adacore.com>
+
+ * s-taprop-linux.adb (Initialize_Lock): Do not allocate a
+ mutex attribute as not needed.
+ (Initialize_TCB): Likewise.
+ (Initialize): Likewise.
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch6.adb (Is_Public_Subprogram_For): New procedure
+ (Process_PPCs): Invariants only apply to public subprograms.
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * sem_util.adb, sem_util.ads, sem_attr.adb, restrict.adb,
+ restrict.ads: Fix for No_Implicit_Aliasing in the renames case.
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * a-finali.ads: Use pragma Pure_12 for this unit
+ * aspects.adb: Add aspect Pure_12
+ * aspects.ads: Add aspect Pure_12
+ * opt.ads: Add note on Pure_12
+ * par-prag.adb: Add dummy entry for Pure_12
+ * sem_prag.adb: Implement Pure_12 pragma
+ * snames.ads-tmpl: Add Entry for Pure_12
+
+2011-11-21 Sergey Rybin <rybin@adacore.com frybin>
+
+ * vms_data.ads: Add qualifiers for new gnatpp options
+ '--call_threshold' and '--par_threshold".
+ * gnat_ugn.texi: Add description for new gnatpp options
+ '--call_threshold' and '--par_threshold".
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * lib.ads: Minor reformatting.
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * lib-load.ads: Add comment.
+
+2011-11-21 Gary Dismukes <dismukes@adacore.com>
+
+ * sem_elab.adb: Minor reformatting
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * exp_ch6.adb: Minor reformatting.
+
+2011-11-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch12.adb (Check_Formal_Package_Instance): If a formal
+ subprogram of the formal package is covered by an others
+ association with a box initialization, no check is needed
+ against the actual in the instantiation of the formal package.
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * sem_elab.adb (Check_Internal_Call_Continue): Suppress junk
+ elab warning from within precondition/postcondition etc.
+
+2011-11-21 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_ch6.adb (Expand_Actuals): In Ada 2012, a function call
+ with out parameters may generate assignments to force constraint
+ checks. These checks must be properly placed in the code after the
+ declaration or statement that contains the call.
+
+2011-11-21 Fedor Rybin <frybin@adacore.com>
+
+ * gnat_ugn.texi: Adding info on current gnattest limitations an
+ support of -X option.
+
+2011-11-21 Robert Dewar <dewar@adacore.com>
+
+ * a-cfdlli.adb, a-cbdlli.adb: Minor reformatting.
+
+2011-11-20 Robert Dewar <dewar@adacore.com>
+
+ * exp_ch6.adb, exp_util.adb: Minor reformatting
+
+2011-11-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * sinfo.ads (Reference): Document that it is OK to set
+ Is_Known_Non_Null on a temporary initialized to a N_Reference
+ node.
+
+2011-11-20 Matthew Heaney <heaney@adacore.com>
+
+ * a-cbdlli.adb, a-cfdlli.adb (Move): Set Last component to 0
+ for Source list.
+
+2011-11-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_ch6.adb (Make_Build_In_Place_Call_In_Assignment):
+ Declare NEW_EXPR local variable and attach the
+ temporary to it. Set Is_Known_Non_Null on the temporary.
+ (Make_Build_In_Place_Call_In_Object_Declaration): Likewise.
+ * exp_util.adb (Remove_Side_Effects): Set Is_Known_Non_Null on
+ the temporary created to hold the 'Reference of the expression,
+ if any.
+ * checks.adb (Install_Null_Excluding_Check): Bail out for the
+ Get_Current_Excep.all.all idiom generated by the expander.
+
+2011-11-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (struct language_function): Add GNAT_RET.
+ (f_gnat_ret): New macro.
+ (struct nrv_data): Add GNAT_RET.
+ (finalize_nrv_unc_r): New helper function.
+ (finalize_nrv): Add GNAT_RET parameter. Copy it into DATA. If the
+ function returns unconstrained, use finalize_nrv_unc_r as callback.
+ (return_value_ok_for_nrv_p): Test the alignment of RET_OBJ only if
+ RET_OBJ is non-null.
+ (Subprogram_Body_to_gnu): Pass GNAT_RET to finalize_nrv.
+ (gnat_to_gnu) <N_Return_Statement>: In the return-unconstrained case,
+ if optimization is enabled, record candidates for the Named Return
+ Value optimization.
+
+2011-11-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (Subprogram_Body_to_gnu): Add comment.
+ (gnat_to_gnu) <N_Return_Statement>: Add 'else' to avoid doing a useless
+ test. Tweak default case.
+ <N_Goto_Statement>: Use better formatting.
+ * gcc-interface/utils2.c (maybe_wrap_malloc): Use INIT_EXPR instead of
+ MODIFY_EXPR to initialize the storage.
+ (build_allocator): Likewise.
+
+2011-11-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Record_Type>: Adjust
+ call to components_to_record.
+ (components_to_record): Add FIRST_FREE_POS parameter. For the variant
+ part, reuse enclosing union even if there is a representation clause
+ on the Unchecked_Union. If there is a variant part, compute the new
+ first free position, if any. Adjust call to self. Use a single field
+ directly only if it hasn't got a representation clause or is placed at
+ offset zero. Create the variant part at offset 0 if all the fields
+ down to this level have a rep clause. Do not chain the variant part
+ immediately and adjust downstream.
+ Do not test ALL_REP before moving the fields without rep clause to the
+ previous level. Call create_rep_part to create the REP part and force
+ a minimum size on it if necessary. Do not chain it immediately.
+ Create a fake REP part if there are fields without rep clause that need
+ to be laid out starting from FIRST_FREE_POS.
+ At the end, chain the REP part and then the variant part.
+ (create_rep_part): New function.
+ (get_rep_part): Minor tweak.
+ * gcc-interface/utils.c (tree_code_for_record_type): Minor tweak.
+
+2011-11-18 Iain Sandoe <iains@gcc.gnu.org>
+
+ PR target/50678
+ * init.c (__gnat_error_handler) [Darwin]: Move workaround to the
+ bug filed as radar #10302855 from __gnat_error_handler to...
+ (__gnat_adjust_context_for_raise) [Darwin]: ...here. New function.
+ (HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE) [Darwin]: Define.
+
+2011-11-18 Tristan Gingold <gingold@adacore.com>
+ Iain Sandoe <iains@gcc.gnu.org>
+
+ PR target/49992
+ * mlib-tgt-specific-darwin.adb (Archive_Indexer_Options): Remove.
+ * gcc-interface/Makefile.in (darwin): Remove ranlib special-casing.
+
2011-11-12 Iain Sandoe <iains@gcc.gnu.org>
* gcc-interface/Makefile.in (stamp-gnatlib-$(RTSDIR)): Don't link
s-oscons.ads.
(OSCONS_CPP, OSCONS_EXTRACT): New.
- (./bldtools/oscons/xoscons): New Target.
- ($(RTSDIR)/s-oscons.ads): New Target.
- (gnatlib): Depend on $(RTSDIR)/s-oscons.ads.
+ (./bldtools/oscons/xoscons): New target.
+ ($(RTSDIR)/s-oscons.ads): Likewise.
+ (gnatlib): Depend on $(RTSDIR)/s-oscons.ads.
* gcc-interface/Make-lang.in (ada/s-oscons.ads) Remove as dependency.
* Make-generated.in: Remove machinery to generate xoscons and
ada/s-oscons.ads.
diff --git a/gcc/ada/Make-generated.in b/gcc/ada/Make-generated.in
index ac52e491eeb..833d47f2582 100644
--- a/gcc/ada/Make-generated.in
+++ b/gcc/ada/Make-generated.in
@@ -72,7 +72,7 @@ $(ADA_GEN_SUBDIR)/stamp-sdefault : $(srcdir)/version.c Makefile
$(ECHO) " S0 : constant String := \"$(prefix)/\";" >>tmp-sdefault.adb
$(ECHO) " S1 : constant String := \"$(ADA_INCLUDE_DIR)/\";" >>tmp-sdefault.adb
$(ECHO) " S2 : constant String := \"$(ADA_RTL_OBJ_DIR)/\";" >>tmp-sdefault.adb
- $(ECHO) " S3 : constant String := \"$(target)/\";" >>tmp-sdefault.adb
+ $(ECHO) " S3 : constant String := \"$(target_noncanonical)/\";" >>tmp-sdefault.adb
$(ECHO) " S4 : constant String := \"$(libsubdir)/\";" >>tmp-sdefault.adb
$(ECHO) " function Include_Dir_Default_Name return String_Ptr is" >>tmp-sdefault.adb
$(ECHO) " begin" >>tmp-sdefault.adb
diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl
index 50e8a96a3d3..5c3e307f713 100644
--- a/gcc/ada/Makefile.rtl
+++ b/gcc/ada/Makefile.rtl
@@ -75,7 +75,9 @@ GNATRTL_TASKING_OBJS= \
s-tpoben$(objext) \
s-tpobop$(objext) \
s-tposen$(objext) \
- s-tratas$(objext) $(EXTRA_GNATRTL_TASKING_OBJS)
+ s-tratas$(objext) \
+ thread$(objext) \
+ $(EXTRA_GNATRTL_TASKING_OBJS)
# Objects needed for non-tasking.
GNATRTL_NONTASKING_OBJS= \
@@ -404,6 +406,7 @@ GNATRTL_NONTASKING_OBJS= \
g-except$(objext) \
g-exctra$(objext) \
g-expect$(objext) \
+ g-exptty$(objext) \
g-flocon$(objext) \
g-heasor$(objext) \
g-hesora$(objext) \
@@ -450,6 +453,7 @@ GNATRTL_NONTASKING_OBJS= \
g-timsta$(objext) \
g-traceb$(objext) \
g-trasym$(objext) \
+ g-tty$(objext) \
g-u3spch$(objext) \
g-utf_32$(objext) \
g-wispch$(objext) \
diff --git a/gcc/ada/a-cbdlli.adb b/gcc/ada/a-cbdlli.adb
index e1f7725d5cd..22000b3c7e4 100644
--- a/gcc/ada/a-cbdlli.adb
+++ b/gcc/ada/a-cbdlli.adb
@@ -27,15 +27,20 @@
-- This unit was originally developed by Matthew J Heaney. --
------------------------------------------------------------------------------
-with System; use type System.Address;
+with Ada.Finalization; use Ada.Finalization;
+with System; use type System.Address;
package body Ada.Containers.Bounded_Doubly_Linked_Lists is
- type Iterator is new
- List_Iterator_Interfaces.Reversible_Iterator with record
- Container : List_Access;
- Node : Count_Type;
+
+ type Iterator is new Limited_Controlled and
+ List_Iterator_Interfaces.Reversible_Iterator with
+ record
+ Container : List_Access;
+ Node : Count_Type;
end record;
+ overriding procedure Finalize (Object : in out Iterator);
+
overriding function First (Object : Iterator) return Cursor;
overriding function Last (Object : Iterator) return Cursor;
@@ -493,6 +498,22 @@ package body Ada.Containers.Bounded_Doubly_Linked_Lists is
return Position.Container.Nodes (Position.Node).Element;
end Element;
+ --------------
+ -- Finalize --
+ --------------
+
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -544,10 +565,23 @@ package body Ada.Containers.Bounded_Doubly_Linked_Lists is
function First (Object : Iterator) return Cursor is
begin
- if Object.Container = null then
- return No_Element;
+ -- The value of the iterator object's Node component influences the
+ -- behavior of the First (and Last) selector function.
+
+ -- When the Node component is 0, this means the iterator object was
+ -- constructed without a start expression, in which case the (forward)
+ -- iteration starts from the (logical) beginning of the entire sequence
+ -- of items (corresponding to Container.First, for a forward iterator).
+
+ -- Otherwise, this is iteration over a partial sequence of items. When
+ -- the Node component is positive, the iterator object was constructed
+ -- with a start expression, that specifies the position from which the
+ -- (forward) partial iteration begins.
+
+ if Object.Node = 0 then
+ return Bounded_Doubly_Linked_Lists.First (Object.Container.all);
else
- return (Object.Container, Object.Container.First);
+ return Cursor'(Object.Container, Object.Node);
end if;
end First;
@@ -1050,9 +1084,7 @@ package body Ada.Containers.Bounded_Doubly_Linked_Lists is
(Container : List;
Process : not null access procedure (Position : Cursor))
is
- C : List renames Container'Unrestricted_Access.all;
- B : Natural renames C.Busy;
-
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
Node : Count_Type := Container.First;
begin
@@ -1075,14 +1107,28 @@ package body Ada.Containers.Bounded_Doubly_Linked_Lists is
function Iterate
(Container : List)
- return List_Iterator_Interfaces.Reversible_Iterator'class
+ return List_Iterator_Interfaces.Reversible_Iterator'Class
is
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- if Container.Length = 0 then
- return Iterator'(null, Count_Type'First);
- else
- return Iterator'(Container'Unrestricted_Access, Container.First);
- end if;
+ -- The value of the Node component influences the behavior of the First
+ -- and Last selector functions of the iterator object. When the Node
+ -- component is 0 (as is the case here), this means the iterator
+ -- object was constructed without a start expression. This is a
+ -- complete iterator, meaning that the iteration starts from the
+ -- (logical) beginning of the sequence of items.
+
+ -- Note: For a forward iterator, Container.First is the beginning, and
+ -- for a reverse iterator, Container.Last is the beginning.
+
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Node => 0)
+ do
+ B := B + 1;
+ end return;
end Iterate;
function Iterate
@@ -1090,9 +1136,48 @@ package body Ada.Containers.Bounded_Doubly_Linked_Lists is
Start : Cursor)
return List_Iterator_Interfaces.Reversible_Iterator'class
is
- It : constant Iterator := (Container'Unrestricted_Access, Start.Node);
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- return It;
+ -- It was formerly the case that when Start = No_Element, the partial
+ -- iterator was defined to behave the same as for a complete iterator,
+ -- and iterate over the entire sequence of items. However, those
+ -- semantics were unintuitive and arguably error-prone (it is too easy
+ -- to accidentally create an endless loop), and so they were changed,
+ -- per the ARG meeting in Denver on 2011/11. However, there was no
+ -- consensus about what positive meaning this corner case should have,
+ -- and so it was decided to simply raise an exception. This does imply,
+ -- however, that it is not possible to use a partial iterator to specify
+ -- an empty sequence of items.
+
+ if Start = No_Element then
+ raise Constraint_Error with
+ "Start position for iterator equals No_Element";
+ end if;
+
+ if Start.Container /= Container'Unrestricted_Access then
+ raise Program_Error with
+ "Start cursor of Iterate designates wrong list";
+ end if;
+
+ pragma Assert (Vet (Start), "Start cursor of Iterate is bad");
+
+ -- The value of the Node component influences the behavior of the First
+ -- and Last selector functions of the iterator object. When the Node
+ -- component is positive (as is the case here), it means that this
+ -- is a partial iteration, over a subset of the complete sequence of
+ -- items. The iterator object was constructed with a start expression,
+ -- indicating the position from which the iteration begins. Note that
+ -- the start position has the same value irrespective of whether this
+ -- is a forward or reverse iteration.
+
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Node => Start.Node)
+ do
+ B := B + 1;
+ end return;
end Iterate;
----------
@@ -1110,10 +1195,23 @@ package body Ada.Containers.Bounded_Doubly_Linked_Lists is
function Last (Object : Iterator) return Cursor is
begin
- if Object.Container = null then
- return No_Element;
+ -- The value of the iterator object's Node component influences the
+ -- behavior of the Last (and First) selector function.
+
+ -- When the Node component is 0, this means the iterator object was
+ -- constructed without a start expression, in which case the (reverse)
+ -- iteration starts from the (logical) beginning of the entire sequence
+ -- (corresponding to Container.Last, for a reverse iterator).
+
+ -- Otherwise, this is iteration over a partial sequence of items. When
+ -- the Node component is positive, the iterator object was constructed
+ -- with a start expression, that specifies the position from which the
+ -- (reverse) partial iteration begins.
+
+ if Object.Node = 0 then
+ return Bounded_Doubly_Linked_Lists.Last (Object.Container.all);
else
- return (Object.Container, Object.Container.Last);
+ return Cursor'(Object.Container, Object.Node);
end if;
end Last;
@@ -1164,18 +1262,66 @@ package body Ada.Containers.Bounded_Doubly_Linked_Lists is
"attempt to tamper with cursors of Source (list is busy)";
end if;
+ -- Clear target, note that this checks busy bits of Target
+
Clear (Target);
- while Source.Length > 0 loop
+ while Source.Length > 1 loop
+ pragma Assert (Source.First in 1 .. Source.Capacity);
+ pragma Assert (Source.Last /= Source.First);
+ pragma Assert (N (Source.First).Prev = 0);
+ pragma Assert (N (Source.Last).Next = 0);
+
+ -- Copy first element from Source to Target
+
X := Source.First;
Append (Target, N (X).Element);
+ -- Unlink first node of Source
+
Source.First := N (X).Next;
N (Source.First).Prev := 0;
Source.Length := Source.Length - 1;
+
+ -- The representation invariants for Source have been restored. It is
+ -- now safe to free the unlinked node, without fear of corrupting the
+ -- active links of Source.
+
+ -- Note that the algorithm we use here models similar algorithms used
+ -- in the unbounded form of the doubly-linked list container. In that
+ -- case, Free is an instantation of Unchecked_Deallocation, which can
+ -- fail (because PE will be raised if controlled Finalize fails), so
+ -- we must defer the call until the last step. Here in the bounded
+ -- form, Free merely links the node we have just "deallocated" onto a
+ -- list of inactive nodes, so technically Free cannot fail. However,
+ -- for consistency, we handle Free the same way here as we do for the
+ -- unbounded form, with the pessimistic assumption that it can fail.
+
Free (Source, X);
end loop;
+
+ if Source.Length = 1 then
+ pragma Assert (Source.First in 1 .. Source.Capacity);
+ pragma Assert (Source.Last = Source.First);
+ pragma Assert (N (Source.First).Prev = 0);
+ pragma Assert (N (Source.Last).Next = 0);
+
+ -- Copy element from Source to Target
+
+ X := Source.First;
+ Append (Target, N (X).Element);
+
+ -- Unlink node of Source
+
+ Source.First := 0;
+ Source.Last := 0;
+ Source.Length := 0;
+
+ -- Return the unlinked node to the free store
+
+ Free (Source, X);
+ end if;
end Move;
----------
@@ -1198,6 +1344,7 @@ package body Ada.Containers.Bounded_Doubly_Linked_Lists is
declare
Nodes : Node_Array renames Position.Container.Nodes;
Node : constant Count_Type := Nodes (Position.Node).Next;
+
begin
if Node = 0 then
return No_Element;
@@ -1211,14 +1358,17 @@ package body Ada.Containers.Bounded_Doubly_Linked_Lists is
(Object : Iterator;
Position : Cursor) return Cursor
is
- Nodes : Node_Array renames Position.Container.Nodes;
- Node : constant Count_Type := Nodes (Position.Node).Next;
begin
- if Position.Node = Object.Container.Last then
+ if Position.Container = null then
return No_Element;
- else
- return (Object.Container, Node);
end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Next designates wrong list";
+ end if;
+
+ return Next (Position);
end Next;
-------------
@@ -1267,14 +1417,17 @@ package body Ada.Containers.Bounded_Doubly_Linked_Lists is
(Object : Iterator;
Position : Cursor) return Cursor
is
- Nodes : Node_Array renames Position.Container.Nodes;
- Node : constant Count_Type := Nodes (Position.Node).Prev;
begin
- if Position.Node = 0 then
+ if Position.Container = null then
return No_Element;
- else
- return (Object.Container, Node);
end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Previous designates wrong list";
+ end if;
+
+ return Previous (Position);
end Previous;
-------------------
diff --git a/gcc/ada/a-cbhama.adb b/gcc/ada/a-cbhama.adb
index d7c75d44aaf..471193079b5 100644
--- a/gcc/ada/a-cbhama.adb
+++ b/gcc/ada/a-cbhama.adb
@@ -34,15 +34,18 @@ with Ada.Containers.Hash_Tables.Generic_Bounded_Keys;
pragma Elaborate_All (Ada.Containers.Hash_Tables.Generic_Bounded_Keys);
with Ada.Containers.Prime_Numbers; use Ada.Containers.Prime_Numbers;
+with Ada.Finalization; use Ada.Finalization;
with System; use type System.Address;
package body Ada.Containers.Bounded_Hashed_Maps is
- type Iterator is new
- Map_Iterator_Interfaces.Forward_Iterator with record
- Container : Map_Access;
- Node : Count_Type;
- end record;
+ type Iterator is new Limited_Controlled and
+ Map_Iterator_Interfaces.Forward_Iterator with
+ record
+ Container : Map_Access;
+ end record;
+
+ overriding procedure Finalize (Object : in out Iterator);
overriding function First (Object : Iterator) return Cursor;
@@ -393,6 +396,22 @@ package body Ada.Containers.Bounded_Hashed_Maps is
HT_Ops.Free (Container, X);
end Exclude;
+ --------------
+ -- Finalize --
+ --------------
+
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -424,14 +443,8 @@ package body Ada.Containers.Bounded_Hashed_Maps is
end First;
function First (Object : Iterator) return Cursor is
- M : constant Map_Access := Object.Container;
- N : constant Count_Type := HT_Ops.First (M.all);
begin
- if N = 0 then
- return No_Element;
- else
- return Cursor'(Object.Container.all'Unchecked_Access, N);
- end if;
+ return Object.Container.First;
end First;
-----------------
@@ -656,7 +669,7 @@ package body Ada.Containers.Bounded_Hashed_Maps is
Process (Cursor'(Container'Unrestricted_Access, Node));
end Process_Node;
- B : Natural renames Container'Unrestricted_Access.Busy;
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
-- Start of processing for Iterate
@@ -675,12 +688,17 @@ package body Ada.Containers.Bounded_Hashed_Maps is
end Iterate;
function Iterate
- (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'class
+ (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'Class
is
- Node : constant Count_Type := HT_Ops.First (Container);
- It : constant Iterator := (Container'Unrestricted_Access, Node);
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- return It;
+ return It : constant Iterator :=
+ (Limited_Controlled with
+ Container => Container'Unrestricted_Access)
+ do
+ B := B + 1;
+ end return;
end Iterate;
---------
@@ -770,11 +788,16 @@ package body Ada.Containers.Bounded_Hashed_Maps is
Position : Cursor) return Cursor
is
begin
- if Position.Node = 0 then
+ if Position.Container = null then
return No_Element;
- else
- return (Object.Container, Next (Position).Node);
end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Next designates wrong map";
+ end if;
+
+ return Next (Position);
end Next;
-------------------
diff --git a/gcc/ada/a-cbhase.adb b/gcc/ada/a-cbhase.adb
index 97a765a6839..cfefc73b6c1 100644
--- a/gcc/ada/a-cbhase.adb
+++ b/gcc/ada/a-cbhase.adb
@@ -34,16 +34,20 @@ with Ada.Containers.Hash_Tables.Generic_Bounded_Keys;
pragma Elaborate_All (Ada.Containers.Hash_Tables.Generic_Bounded_Keys);
with Ada.Containers.Prime_Numbers; use Ada.Containers.Prime_Numbers;
+with Ada.Finalization; use Ada.Finalization;
with System; use type System.Address;
package body Ada.Containers.Bounded_Hashed_Sets is
- type Iterator is new Set_Iterator_Interfaces.Forward_Iterator with record
+ type Iterator is new Limited_Controlled and
+ Set_Iterator_Interfaces.Forward_Iterator with
+ record
Container : Set_Access;
- Position : Cursor;
end record;
+ overriding procedure Finalize (Object : in out Iterator);
+
overriding function First (Object : Iterator) return Cursor;
overriding function Next
@@ -570,6 +574,22 @@ package body Ada.Containers.Bounded_Hashed_Sets is
HT_Ops.Free (Container, X);
end Exclude;
+ --------------
+ -- Finalize --
+ --------------
+
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -596,10 +616,8 @@ package body Ada.Containers.Bounded_Hashed_Sets is
end First;
overriding function First (Object : Iterator) return Cursor is
- Node : constant Count_Type := HT_Ops.First (Object.Container.all);
begin
- return (if Node = 0 then No_Element
- else Cursor'(Object.Container, Node));
+ return Object.Container.First;
end First;
-----------------
@@ -890,7 +908,7 @@ package body Ada.Containers.Bounded_Hashed_Sets is
Process (Cursor'(Container'Unrestricted_Access, Node));
end Process_Node;
- B : Natural renames Container'Unrestricted_Access.Busy;
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
-- Start of processing for Iterate
@@ -909,9 +927,16 @@ package body Ada.Containers.Bounded_Hashed_Sets is
end Iterate;
function Iterate (Container : Set)
- return Set_Iterator_Interfaces.Forward_Iterator'Class is
+ return Set_Iterator_Interfaces.Forward_Iterator'Class
+ is
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- return Iterator'(Container'Unrestricted_Access, First (Container));
+ B := B + 1;
+
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Container'Unrestricted_Access);
end Iterate;
------------
@@ -982,12 +1007,16 @@ package body Ada.Containers.Bounded_Hashed_Sets is
Position : Cursor) return Cursor
is
begin
+ if Position.Container = null then
+ return No_Element;
+ end if;
+
if Position.Container /= Object.Container then
raise Program_Error with
- "Position cursor designates wrong set";
+ "Position cursor of Next designates wrong set";
end if;
- return (if Position.Node = 0 then No_Element else Next (Position));
+ return Next (Position);
end Next;
-------------
@@ -1599,7 +1628,7 @@ package body Ada.Containers.Bounded_Hashed_Sets is
begin
if Node = 0 then
- raise Constraint_Error with "key not in map";
+ raise Constraint_Error with "key not in map"; -- ??? "set"
end if;
return Container.Nodes (Node).Element;
diff --git a/gcc/ada/a-cbmutr.adb b/gcc/ada/a-cbmutr.adb
index 7ad2de4e62a..acda30f63c6 100644
--- a/gcc/ada/a-cbmutr.adb
+++ b/gcc/ada/a-cbmutr.adb
@@ -27,30 +27,38 @@
-- This unit was originally developed by Matthew J Heaney. --
------------------------------------------------------------------------------
-with System; use type System.Address;
+with Ada.Finalization; use Ada.Finalization;
+with System; use type System.Address;
+
package body Ada.Containers.Bounded_Multiway_Trees is
No_Node : constant Count_Type'Base := -1;
- type Iterator is new Tree_Iterator_Interfaces.Forward_Iterator with
+ type Iterator is new Limited_Controlled and
+ Tree_Iterator_Interfaces.Forward_Iterator with
record
Container : Tree_Access;
Position : Cursor;
From_Root : Boolean;
end record;
+ overriding procedure Finalize (Object : in out Iterator);
+
overriding function First (Object : Iterator) return Cursor;
overriding function Next
(Object : Iterator;
Position : Cursor) return Cursor;
- type Child_Iterator is new Tree_Iterator_Interfaces.Reversible_Iterator with
+ type Child_Iterator is new Limited_Controlled and
+ Tree_Iterator_Interfaces.Reversible_Iterator with
record
Container : Tree_Access;
Position : Cursor;
end record;
+ overriding procedure Finalize (Object : in out Child_Iterator);
+
overriding function First (Object : Child_Iterator) return Cursor;
overriding function Next
@@ -1229,6 +1237,34 @@ package body Ada.Containers.Bounded_Multiway_Trees is
Right_Subtree => Right_Subtree);
end Equal_Subtree;
+ --------------
+ -- Finalize --
+ --------------
+
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
+ procedure Finalize (Object : in out Child_Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -1732,8 +1768,7 @@ package body Ada.Containers.Bounded_Multiway_Trees is
(Container : Tree;
Process : not null access procedure (Position : Cursor))
is
- T : Tree renames Container'Unrestricted_Access.all;
- B : Integer renames T.Busy;
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
begin
if Container.Count = 0 then
@@ -1758,13 +1793,19 @@ package body Ada.Containers.Bounded_Multiway_Trees is
function Iterate (Container : Tree)
return Tree_Iterator_Interfaces.Forward_Iterator'Class
is
- Root_Cursor : constant Cursor :=
- (Container'Unrestricted_Access, Root_Node (Container));
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+ RC : constant Cursor :=
+ (Container'Unrestricted_Access, Root_Node (Container));
+
begin
- return
- Iterator'(Container'Unrestricted_Access,
- First_Child (Root_Cursor),
- From_Root => True);
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Position => First_Child (RC),
+ From_Root => True)
+ do
+ B := B + 1;
+ end return;
end Iterate;
----------------------
@@ -1786,9 +1827,9 @@ package body Ada.Containers.Bounded_Multiway_Trees is
end if;
declare
- NN : Tree_Node_Array renames Parent.Container.Nodes;
- B : Integer renames Parent.Container.Busy;
+ B : Natural renames Parent.Container.Busy;
C : Count_Type;
+ NN : Tree_Node_Array renames Parent.Container.Nodes;
begin
B := B + 1;
@@ -1836,9 +1877,16 @@ package body Ada.Containers.Bounded_Multiway_Trees is
Parent : Cursor)
return Tree_Iterator_Interfaces.Reversible_Iterator'Class
is
- pragma Unreferenced (Container);
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- return Child_Iterator'(Parent.Container, Parent);
+ return It : constant Child_Iterator :=
+ Child_Iterator'(Limited_Controlled with
+ Container => Parent.Container,
+ Position => Parent)
+ do
+ B := B + 1;
+ end return;
end Iterate_Children;
---------------------
@@ -1849,8 +1897,17 @@ package body Ada.Containers.Bounded_Multiway_Trees is
(Position : Cursor)
return Tree_Iterator_Interfaces.Forward_Iterator'Class
is
+ B : Natural renames Position.Container.all.Busy;
+
begin
- return Iterator'(Position.Container, Position, From_Root => False);
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Position.Container,
+ Position => Position,
+ From_Root => False)
+ do
+ B := B + 1;
+ end return;
end Iterate_Subtree;
procedure Iterate_Subtree
@@ -1869,7 +1926,7 @@ package body Ada.Containers.Bounded_Multiway_Trees is
declare
T : Tree renames Position.Container.all;
- B : Integer renames T.Busy;
+ B : Natural renames T.Busy;
begin
B := B + 1;
@@ -2259,8 +2316,8 @@ package body Ada.Containers.Bounded_Multiway_Trees is
declare
T : Tree renames Position.Container.all'Unrestricted_Access.all;
- B : Integer renames T.Busy;
- L : Integer renames T.Lock;
+ B : Natural renames T.Busy;
+ L : Natural renames T.Lock;
begin
B := B + 1;
@@ -2529,7 +2586,7 @@ package body Ada.Containers.Bounded_Multiway_Trees is
declare
NN : Tree_Node_Array renames Parent.Container.Nodes;
- B : Integer renames Parent.Container.Busy;
+ B : Natural renames Parent.Container.Busy;
C : Count_Type;
begin
@@ -3209,8 +3266,8 @@ package body Ada.Containers.Bounded_Multiway_Trees is
declare
T : Tree renames Position.Container.all'Unrestricted_Access.all;
- B : Integer renames T.Busy;
- L : Integer renames T.Lock;
+ B : Natural renames T.Busy;
+ L : Natural renames T.Lock;
begin
B := B + 1;
diff --git a/gcc/ada/a-cborma.adb b/gcc/ada/a-cborma.adb
index 4cc2686bb22..141350956c1 100644
--- a/gcc/ada/a-cborma.adb
+++ b/gcc/ada/a-cborma.adb
@@ -35,19 +35,22 @@ with Ada.Containers.Red_Black_Trees.Generic_Bounded_Keys;
pragma Elaborate_All
(Ada.Containers.Red_Black_Trees.Generic_Bounded_Keys);
-with System; use type System.Address;
+with Ada.Finalization; use Ada.Finalization;
+with System; use type System.Address;
package body Ada.Containers.Bounded_Ordered_Maps is
- type Iterator is new
- Map_Iterator_Interfaces.Reversible_Iterator with record
- Container : Map_Access;
- Node : Count_Type;
- end record;
+ type Iterator is new Limited_Controlled and
+ Map_Iterator_Interfaces.Reversible_Iterator with
+ record
+ Container : Map_Access;
+ Node : Count_Type;
+ end record;
- overriding function First (Object : Iterator) return Cursor;
+ overriding procedure Finalize (Object : in out Iterator);
- overriding function Last (Object : Iterator) return Cursor;
+ overriding function First (Object : Iterator) return Cursor;
+ overriding function Last (Object : Iterator) return Cursor;
overriding function Next
(Object : Iterator;
@@ -551,6 +554,22 @@ package body Ada.Containers.Bounded_Ordered_Maps is
end if;
end Exclude;
+ --------------
+ -- Finalize --
+ --------------
+
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -579,12 +598,24 @@ package body Ada.Containers.Bounded_Ordered_Maps is
end First;
function First (Object : Iterator) return Cursor is
- F : constant Count_Type := Object.Container.First;
begin
- if F = 0 then
- return No_Element;
+ -- The value of the iterator object's Node component influences the
+ -- behavior of the First (and Last) selector function.
+
+ -- When the Node component is 0, this means the iterator object was
+ -- constructed without a start expression, in which case the (forward)
+ -- iteration starts from the (logical) beginning of the entire sequence
+ -- of items (corresponding to Container.First, for a forward iterator).
+
+ -- Otherwise, this is iteration over a partial sequence of items. When
+ -- the Node component is positive, the iterator object was constructed
+ -- with a start expression, that specifies the position from which the
+ -- (forward) partial iteration begins.
+
+ if Object.Node = 0 then
+ return Bounded_Ordered_Maps.First (Object.Container.all);
else
- return Cursor'(Object.Container.all'Unchecked_Access, F);
+ return Cursor'(Object.Container, Object.Node);
end if;
end First;
@@ -886,22 +917,77 @@ package body Ada.Containers.Bounded_Ordered_Maps is
end Iterate;
function Iterate
- (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'class
+ (Container : Map) return Map_Iterator_Interfaces.Reversible_Iterator'Class
is
- It : constant Iterator :=
- (Container'Unrestricted_Access, Container.First);
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- return It;
+ -- The value of the Node component influences the behavior of the First
+ -- and Last selector functions of the iterator object. When the Node
+ -- component is 0 (as is the case here), this means the iterator object
+ -- was constructed without a start expression. This is a complete
+ -- iterator, meaning that the iteration starts from the (logical)
+ -- beginning of the sequence of items.
+
+ -- Note: For a forward iterator, Container.First is the beginning, and
+ -- for a reverse iterator, Container.Last is the beginning.
+
+ return It : constant Iterator :=
+ (Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Node => Container.First)
+ do
+ B := B + 1;
+ end return;
end Iterate;
function Iterate
(Container : Map;
Start : Cursor)
- return Map_Iterator_Interfaces.Reversible_Iterator'class
+ return Map_Iterator_Interfaces.Reversible_Iterator'Class
is
- It : constant Iterator := (Container'Unrestricted_Access, Start.Node);
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- return It;
+ -- Iterator was defined to behave the same as for a complete iterator,
+ -- and iterate over the entire sequence of items. However, those
+ -- semantics were unintuitive and arguably error-prone (it is too easy
+ -- to accidentally create an endless loop), and so they were changed,
+ -- per the ARG meeting in Denver on 2011/11. However, there was no
+ -- consensus about what positive meaning this corner case should have,
+ -- and so it was decided to simply raise an exception. This does imply,
+ -- however, that it is not possible to use a partial iterator to specify
+ -- an empty sequence of items.
+
+ if Start = No_Element then
+ raise Constraint_Error with
+ "Start position for iterator equals No_Element";
+ end if;
+
+ if Start.Container /= Container'Unrestricted_Access then
+ raise Program_Error with
+ "Start cursor of Iterate designates wrong map";
+ end if;
+
+ pragma Assert (Vet (Container, Start.Node),
+ "Start cursor of Iterate is bad");
+
+ -- The value of the Node component influences the behavior of the First
+ -- and Last selector functions of the iterator object. When the Node
+ -- component is positive (as is the case here), it means that this
+ -- is a partial iteration, over a subset of the complete sequence of
+ -- items. The iterator object was constructed with a start expression,
+ -- indicating the position from which the iteration begins. (Note that
+ -- the start position has the same value irrespective of whether this
+ -- is a forward or reverse iteration.)
+
+ return It : constant Iterator :=
+ (Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Node => Start.Node)
+ do
+ B := B + 1;
+ end return;
end Iterate;
---------
@@ -935,12 +1021,24 @@ package body Ada.Containers.Bounded_Ordered_Maps is
end Last;
function Last (Object : Iterator) return Cursor is
- F : constant Count_Type := Object.Container.Last;
begin
- if F = 0 then
- return No_Element;
+ -- The value of the iterator object's Node component influences the
+ -- behavior of the Last (and First) selector function.
+
+ -- When the Node component is 0, this means the iterator object was
+ -- constructed without a start expression, in which case the (reverse)
+ -- iteration starts from the (logical) beginning of the entire sequence
+ -- (corresponding to Container.Last, for a reverse iterator).
+
+ -- Otherwise, this is iteration over a partial sequence of items. When
+ -- the Node component is positive, the iterator object was constructed
+ -- with a start expression, that specifies the position from which the
+ -- (reverse) partial iteration begins.
+
+ if Object.Node = 0 then
+ return Bounded_Ordered_Maps.Last (Object.Container.all);
else
- return Cursor'(Object.Container.all'Unchecked_Access, F);
+ return Cursor'(Object.Container, Object.Node);
end if;
end Last;
@@ -1044,8 +1142,16 @@ package body Ada.Containers.Bounded_Ordered_Maps is
(Object : Iterator;
Position : Cursor) return Cursor
is
- pragma Unreferenced (Object);
begin
+ if Position.Container = null then
+ return No_Element;
+ end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Next designates wrong map";
+ end if;
+
return Next (Position);
end Next;
@@ -1095,8 +1201,16 @@ package body Ada.Containers.Bounded_Ordered_Maps is
(Object : Iterator;
Position : Cursor) return Cursor
is
- pragma Unreferenced (Object);
begin
+ if Position.Container = null then
+ return No_Element;
+ end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Previous designates wrong map";
+ end if;
+
return Previous (Position);
end Previous;
diff --git a/gcc/ada/a-cborma.ads b/gcc/ada/a-cborma.ads
index e1f9f08f379..05c55730f10 100644
--- a/gcc/ada/a-cborma.ads
+++ b/gcc/ada/a-cborma.ads
@@ -227,17 +227,18 @@ package Ada.Containers.Bounded_Ordered_Maps is
(Container : Map;
Process : not null access procedure (Position : Cursor));
+ procedure Reverse_Iterate
+ (Container : Map;
+ Process : not null access procedure (Position : Cursor));
+
function Iterate
- (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'class;
+ (Container : Map)
+ return Map_Iterator_Interfaces.Reversible_Iterator'Class;
function Iterate
(Container : Map;
Start : Cursor)
- return Map_Iterator_Interfaces.Reversible_Iterator'class;
-
- procedure Reverse_Iterate
- (Container : Map;
- Process : not null access procedure (Position : Cursor));
+ return Map_Iterator_Interfaces.Reversible_Iterator'Class;
private
diff --git a/gcc/ada/a-cborse.adb b/gcc/ada/a-cborse.adb
index 674d2abee33..17fa7950237 100644
--- a/gcc/ada/a-cborse.adb
+++ b/gcc/ada/a-cborse.adb
@@ -38,19 +38,22 @@ with Ada.Containers.Red_Black_Trees.Generic_Bounded_Set_Operations;
pragma Elaborate_All
(Ada.Containers.Red_Black_Trees.Generic_Bounded_Set_Operations);
+with Ada.Finalization; use Ada.Finalization;
with System; use type System.Address;
package body Ada.Containers.Bounded_Ordered_Sets is
- type Iterator is new
- Ordered_Set_Iterator_Interfaces.Reversible_Iterator with record
- Container : access constant Set;
- Node : Count_Type;
- end record;
+ type Iterator is new Limited_Controlled and
+ Set_Iterator_Interfaces.Reversible_Iterator with
+ record
+ Container : Set_Access;
+ Node : Count_Type;
+ end record;
- overriding function First (Object : Iterator) return Cursor;
+ overriding procedure Finalize (Object : in out Iterator);
- overriding function Last (Object : Iterator) return Cursor;
+ overriding function First (Object : Iterator) return Cursor;
+ overriding function Last (Object : Iterator) return Cursor;
overriding function Next
(Object : Iterator;
@@ -568,6 +571,22 @@ package body Ada.Containers.Bounded_Ordered_Sets is
end if;
end Exclude;
+ --------------
+ -- Finalize --
+ --------------
+
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -591,9 +610,24 @@ package body Ada.Containers.Bounded_Ordered_Sets is
function First (Object : Iterator) return Cursor is
begin
- return (if Object.Container.First = 0 then No_Element
- else Cursor'(Object.Container.all'Unrestricted_Access,
- Object.Container.First));
+ -- The value of the iterator object's Node component influences the
+ -- behavior of the First (and Last) selector function.
+
+ -- When the Node component is 0, this means the iterator object was
+ -- constructed without a start expression, in which case the (forward)
+ -- iteration starts from the (logical) beginning of the entire sequence
+ -- of items (corresponding to Container.First, for a forward iterator).
+
+ -- Otherwise, this is iteration over a partial sequence of items. When
+ -- the Node component is positive, the iterator object was constructed
+ -- with a start expression, that specifies the position from which the
+ -- (forward) partial iteration begins.
+
+ if Object.Node = 0 then
+ return Bounded_Ordered_Sets.First (Object.Container.all);
+ else
+ return Cursor'(Object.Container, Object.Node);
+ end if;
end First;
-------------------
@@ -1206,22 +1240,76 @@ package body Ada.Containers.Bounded_Ordered_Sets is
end Iterate;
function Iterate (Container : Set)
- return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
+ return Set_Iterator_Interfaces.Reversible_Iterator'class
is
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- if Container.Length = 0 then
- return Iterator'(null, 0);
- else
- return Iterator'(Container'Unchecked_Access, Container.First);
- end if;
+ -- The value of the Node component influences the behavior of the First
+ -- and Last selector functions of the iterator object. When the Node
+ -- component is 0 (as is the case here), this means the iterator object
+ -- was constructed without a start expression. This is a complete
+ -- iterator, meaning that the iteration starts from the (logical)
+ -- beginning of the sequence of items.
+
+ -- Note: For a forward iterator, Container.First is the beginning, and
+ -- for a reverse iterator, Container.Last is the beginning.
+
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Node => 0)
+ do
+ B := B + 1;
+ end return;
end Iterate;
function Iterate (Container : Set; Start : Cursor)
- return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
+ return Set_Iterator_Interfaces.Reversible_Iterator'class
is
- It : constant Iterator := (Container'Unchecked_Access, Start.Node);
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- return It;
+ -- It was formerly the case that when Start = No_Element, the partial
+ -- iterator was defined to behave the same as for a complete iterator,
+ -- and iterate over the entire sequence of items. However, those
+ -- semantics were unintuitive and arguably error-prone (it is too easy
+ -- to accidentally create an endless loop), and so they were changed,
+ -- per the ARG meeting in Denver on 2011/11. However, there was no
+ -- consensus about what positive meaning this corner case should have,
+ -- and so it was decided to simply raise an exception. This does imply,
+ -- however, that it is not possible to use a partial iterator to specify
+ -- an empty sequence of items.
+
+ if Start = No_Element then
+ raise Constraint_Error with
+ "Start position for iterator equals No_Element";
+ end if;
+
+ if Start.Container /= Container'Unrestricted_Access then
+ raise Program_Error with
+ "Start cursor of Iterate designates wrong set";
+ end if;
+
+ pragma Assert (Vet (Container, Start.Node),
+ "Start cursor of Iterate is bad");
+
+ -- The value of the Node component influences the behavior of the First
+ -- and Last selector functions of the iterator object. When the Node
+ -- component is positive (as is the case here), it means that this
+ -- is a partial iteration, over a subset of the complete sequence of
+ -- items. The iterator object was constructed with a start expression,
+ -- indicating the position from which the iteration begins. (Note that
+ -- the start position has the same value irrespective of whether this
+ -- is a forward or reverse iteration.)
+
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Node => Start.Node)
+ do
+ B := B + 1;
+ end return;
end Iterate;
----------
@@ -1236,9 +1324,24 @@ package body Ada.Containers.Bounded_Ordered_Sets is
function Last (Object : Iterator) return Cursor is
begin
- return (if Object.Container.Last = 0 then No_Element
- else Cursor'(Object.Container.all'Unrestricted_Access,
- Object.Container.Last));
+ -- The value of the iterator object's Node component influences the
+ -- behavior of the Last (and First) selector function.
+
+ -- When the Node component is 0, this means the iterator object was
+ -- constructed without a start expression, in which case the (reverse)
+ -- iteration starts from the (logical) beginning of the entire sequence
+ -- (corresponding to Container.Last, for a reverse iterator).
+
+ -- Otherwise, this is iteration over a partial sequence of items. When
+ -- the Node component is positive, the iterator object was constructed
+ -- with a start expression, that specifies the position from which the
+ -- (reverse) partial iteration begins.
+
+ if Object.Node = 0 then
+ return Bounded_Ordered_Sets.Last (Object.Container.all);
+ else
+ return Cursor'(Object.Container, Object.Node);
+ end if;
end Last;
------------------
@@ -1323,8 +1426,16 @@ package body Ada.Containers.Bounded_Ordered_Sets is
end Next;
function Next (Object : Iterator; Position : Cursor) return Cursor is
- pragma Unreferenced (Object);
begin
+ if Position.Container = null then
+ return No_Element;
+ end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Next designates wrong set";
+ end if;
+
return Next (Position);
end Next;
@@ -1374,8 +1485,16 @@ package body Ada.Containers.Bounded_Ordered_Sets is
end Previous;
function Previous (Object : Iterator; Position : Cursor) return Cursor is
- pragma Unreferenced (Object);
begin
+ if Position.Container = null then
+ return No_Element;
+ end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Previous designates wrong set";
+ end if;
+
return Previous (Position);
end Previous;
diff --git a/gcc/ada/a-cborse.ads b/gcc/ada/a-cborse.ads
index 0c8ae6b1703..9c4fdb4f31d 100644
--- a/gcc/ada/a-cborse.ads
+++ b/gcc/ada/a-cborse.ads
@@ -31,9 +31,9 @@
-- This unit was originally developed by Matthew J Heaney. --
------------------------------------------------------------------------------
-with Ada.Iterator_Interfaces;
private with Ada.Containers.Red_Black_Trees;
with Ada.Streams; use Ada.Streams;
+with Ada.Iterator_Interfaces;
generic
type Element_Type is private;
@@ -62,7 +62,7 @@ package Ada.Containers.Bounded_Ordered_Sets is
No_Element : constant Cursor;
function Has_Element (Position : Cursor) return Boolean;
- package Ordered_Set_Iterator_Interfaces is new
+ package Set_Iterator_Interfaces is new
Ada.Iterator_Interfaces (Cursor, Has_Element);
type Constant_Reference_Type
@@ -212,12 +212,12 @@ package Ada.Containers.Bounded_Ordered_Sets is
function Iterate
(Container : Set)
- return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class;
+ return Set_Iterator_Interfaces.Reversible_Iterator'class;
function Iterate
(Container : Set;
Start : Cursor)
- return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class;
+ return Set_Iterator_Interfaces.Reversible_Iterator'class;
generic
type Key_Type (<>) is private;
diff --git a/gcc/ada/a-cdlili.adb b/gcc/ada/a-cdlili.adb
index 8b513222ef8..12242583ebe 100644
--- a/gcc/ada/a-cdlili.adb
+++ b/gcc/ada/a-cdlili.adb
@@ -27,17 +27,20 @@
-- This unit was originally developed by Matthew J Heaney. --
------------------------------------------------------------------------------
-with System; use type System.Address;
-
with Ada.Unchecked_Deallocation;
+with System; use type System.Address;
package body Ada.Containers.Doubly_Linked_Lists is
- type Iterator is new
- List_Iterator_Interfaces.Reversible_Iterator with record
- Container : List_Access;
- Node : Node_Access;
+
+ type Iterator is new Limited_Controlled and
+ List_Iterator_Interfaces.Reversible_Iterator with
+ record
+ Container : List_Access;
+ Node : Node_Access;
end record;
+ overriding procedure Finalize (Object : in out Iterator);
+
overriding function First (Object : Iterator) return Cursor;
overriding function Last (Object : Iterator) return Cursor;
@@ -395,6 +398,22 @@ package body Ada.Containers.Doubly_Linked_Lists is
return Position.Node.Element;
end Element;
+ --------------
+ -- Finalize --
+ --------------
+
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -421,7 +440,7 @@ package body Ada.Containers.Doubly_Linked_Lists is
while Node /= null loop
if Node.Element = Item then
- return Cursor'(Container'Unchecked_Access, Node);
+ return Cursor'(Container'Unrestricted_Access, Node);
end if;
Node := Node.Next;
@@ -440,15 +459,28 @@ package body Ada.Containers.Doubly_Linked_Lists is
return No_Element;
end if;
- return Cursor'(Container'Unchecked_Access, Container.First);
+ return Cursor'(Container'Unrestricted_Access, Container.First);
end First;
function First (Object : Iterator) return Cursor is
begin
- if Object.Container = null then
- return No_Element;
+ -- The value of the iterator object's Node component influences the
+ -- behavior of the First (and Last) selector function.
+
+ -- When the Node component is null, this means the iterator object was
+ -- constructed without a start expression, in which case the (forward)
+ -- iteration starts from the (logical) beginning of the entire sequence
+ -- of items (corresponding to Container.First, for a forward iterator).
+
+ -- Otherwise, this is iteration over a partial sequence of items. When
+ -- the Node component is non-null, the iterator object was constructed
+ -- with a start expression, that specifies the position from which the
+ -- (forward) partial iteration begins.
+
+ if Object.Node = null then
+ return Doubly_Linked_Lists.First (Object.Container.all);
else
- return (Object.Container, Object.Container.First);
+ return Cursor'(Object.Container, Object.Node);
end if;
end First;
@@ -843,9 +875,7 @@ package body Ada.Containers.Doubly_Linked_Lists is
(Container : List;
Process : not null access procedure (Position : Cursor))
is
- C : List renames Container'Unrestricted_Access.all;
- B : Natural renames C.Busy;
-
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
Node : Node_Access := Container.First;
begin
@@ -853,7 +883,7 @@ package body Ada.Containers.Doubly_Linked_Lists is
begin
while Node /= null loop
- Process (Cursor'(Container'Unchecked_Access, Node));
+ Process (Cursor'(Container'Unrestricted_Access, Node));
Node := Node.Next;
end loop;
exception
@@ -866,22 +896,75 @@ package body Ada.Containers.Doubly_Linked_Lists is
end Iterate;
function Iterate (Container : List)
- return List_Iterator_Interfaces.Reversible_Iterator'class
+ return List_Iterator_Interfaces.Reversible_Iterator'Class
is
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- if Container.Length = 0 then
- return Iterator'(null, null);
- else
- return Iterator'(Container'Unchecked_Access, Container.First);
- end if;
+ -- The value of the Node component influences the behavior of the First
+ -- and Last selector functions of the iterator object. When the Node
+ -- component is null (as is the case here), this means the iterator
+ -- object was constructed without a start expression. This is a
+ -- complete iterator, meaning that the iteration starts from the
+ -- (logical) beginning of the sequence of items.
+
+ -- Note: For a forward iterator, Container.First is the beginning, and
+ -- for a reverse iterator, Container.Last is the beginning.
+
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Node => null)
+ do
+ B := B + 1;
+ end return;
end Iterate;
function Iterate (Container : List; Start : Cursor)
- return List_Iterator_Interfaces.Reversible_Iterator'class
+ return List_Iterator_Interfaces.Reversible_Iterator'Class
is
- It : constant Iterator := (Container'Unchecked_Access, Start.Node);
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- return It;
+ -- It was formerly the case that when Start = No_Element, the partial
+ -- iterator was defined to behave the same as for a complete iterator,
+ -- and iterate over the entire sequence of items. However, those
+ -- semantics were unintuitive and arguably error-prone (it is too easy
+ -- to accidentally create an endless loop), and so they were changed,
+ -- per the ARG meeting in Denver on 2011/11. However, there was no
+ -- consensus about what positive meaning this corner case should have,
+ -- and so it was decided to simply raise an exception. This does imply,
+ -- however, that it is not possible to use a partial iterator to specify
+ -- an empty sequence of items.
+
+ if Start = No_Element then
+ raise Constraint_Error with
+ "Start position for iterator equals No_Element";
+ end if;
+
+ if Start.Container /= Container'Unrestricted_Access then
+ raise Program_Error with
+ "Start cursor of Iterate designates wrong list";
+ end if;
+
+ pragma Assert (Vet (Start), "Start cursor of Iterate is bad");
+
+ -- The value of the Node component influences the behavior of the First
+ -- and Last selector functions of the iterator object. When the Node
+ -- component is non-null (as is the case here), it means that this
+ -- is a partial iteration, over a subset of the complete sequence of
+ -- items. The iterator object was constructed with a start expression,
+ -- indicating the position from which the iteration begins. Note that
+ -- the start position has the same value irrespective of whether this
+ -- is a forward or reverse iteration.
+
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Node => Start.Node)
+ do
+ B := B + 1;
+ end return;
end Iterate;
----------
@@ -894,15 +977,28 @@ package body Ada.Containers.Doubly_Linked_Lists is
return No_Element;
end if;
- return Cursor'(Container'Unchecked_Access, Container.Last);
+ return Cursor'(Container'Unrestricted_Access, Container.Last);
end Last;
function Last (Object : Iterator) return Cursor is
begin
- if Object.Container = null then
- return No_Element;
+ -- The value of the iterator object's Node component influences the
+ -- behavior of the Last (and First) selector function.
+
+ -- When the Node component is null, this means the iterator object was
+ -- constructed without a start expression, in which case the (reverse)
+ -- iteration starts from the (logical) beginning of the entire sequence
+ -- (corresponding to Container.Last, for a reverse iterator).
+
+ -- Otherwise, this is iteration over a partial sequence of items. When
+ -- the Node component is non-null, the iterator object was constructed
+ -- with a start expression, that specifies the position from which the
+ -- (reverse) partial iteration begins.
+
+ if Object.Node = null then
+ return Doubly_Linked_Lists.Last (Object.Container.all);
else
- return (Object.Container, Object.Container.Last);
+ return Cursor'(Object.Container, Object.Node);
end if;
end Last;
@@ -992,11 +1088,16 @@ package body Ada.Containers.Doubly_Linked_Lists is
Position : Cursor) return Cursor
is
begin
- if Position.Node = Object.Container.Last then
+ if Position.Container = null then
return No_Element;
- else
- return (Object.Container, Position.Node.Next);
end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Next designates wrong list";
+ end if;
+
+ return Next (Position);
end Next;
-------------
@@ -1046,11 +1147,16 @@ package body Ada.Containers.Doubly_Linked_Lists is
Position : Cursor) return Cursor
is
begin
- if Position.Node = Position.Container.First then
+ if Position.Container = null then
return No_Element;
- else
- return (Object.Container, Position.Node.Prev);
end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Previous designates wrong list";
+ end if;
+
+ return Previous (Position);
end Previous;
-------------------
@@ -1338,7 +1444,7 @@ package body Ada.Containers.Doubly_Linked_Lists is
while Node /= null loop
if Node.Element = Item then
- return Cursor'(Container'Unchecked_Access, Node);
+ return Cursor'(Container'Unrestricted_Access, Node);
end if;
Node := Node.Prev;
@@ -1365,7 +1471,7 @@ package body Ada.Containers.Doubly_Linked_Lists is
begin
while Node /= null loop
- Process (Cursor'(Container'Unchecked_Access, Node));
+ Process (Cursor'(Container'Unrestricted_Access, Node));
Node := Node.Prev;
end loop;
diff --git a/gcc/ada/a-cdlili.ads b/gcc/ada/a-cdlili.ads
index 2de03e520aa..0e6437602f5 100644
--- a/gcc/ada/a-cdlili.ads
+++ b/gcc/ada/a-cdlili.ads
@@ -306,7 +306,7 @@ private
for List'Write use Write;
- type List_Access is access constant List;
+ type List_Access is access all List;
for List_Access'Storage_Size use 0;
type Cursor is
diff --git a/gcc/ada/a-cfdlli.adb b/gcc/ada/a-cfdlli.adb
index 93a88a725d6..3c73c0467aa 100644
--- a/gcc/ada/a-cfdlli.adb
+++ b/gcc/ada/a-cfdlli.adb
@@ -743,7 +743,6 @@ package body Ada.Containers.Formal_Doubly_Linked_Lists is
begin
if Before.Node /= 0 then
- null;
pragma Assert (Vet (Container, Before), "bad cursor in Insert");
end if;
@@ -793,7 +792,6 @@ package body Ada.Containers.Formal_Doubly_Linked_Lists is
begin
if Before.Node /= 0 then
- null;
pragma Assert (Vet (Container, Before), "bad cursor in Insert");
end if;
@@ -1007,16 +1005,62 @@ package body Ada.Containers.Formal_Doubly_Linked_Lists is
Clear (Target);
- while Source.Length > 0 loop
+ while Source.Length > 1 loop
+ pragma Assert (Source.First in 1 .. Source.Capacity);
+ pragma Assert (Source.Last /= Source.First);
+ pragma Assert (N (Source.First).Prev = 0);
+ pragma Assert (N (Source.Last).Next = 0);
+
+ -- Copy first element from Source to Target
+
X := Source.First;
Append (Target, N (X).Element); -- optimize away???
+ -- Unlink first node of Source
+
Source.First := N (X).Next;
N (Source.First).Prev := 0;
Source.Length := Source.Length - 1;
+
+ -- The representation invariants for Source have been restored. It is
+ -- now safe to free the unlinked node, without fear of corrupting the
+ -- active links of Source.
+
+ -- Note that the algorithm we use here models similar algorithms used
+ -- in the unbounded form of the doubly-linked list container. In that
+ -- case, Free is an instantation of Unchecked_Deallocation, which can
+ -- fail (because PE will be raised if controlled Finalize fails), so
+ -- we must defer the call until the last step. Here in the bounded
+ -- form, Free merely links the node we have just "deallocated" onto a
+ -- list of inactive nodes, so technically Free cannot fail. However,
+ -- for consistency, we handle Free the same way here as we do for the
+ -- unbounded form, with the pessimistic assumption that it can fail.
+
Free (Source, X);
end loop;
+
+ if Source.Length = 1 then
+ pragma Assert (Source.First in 1 .. Source.Capacity);
+ pragma Assert (Source.Last = Source.First);
+ pragma Assert (N (Source.First).Prev = 0);
+ pragma Assert (N (Source.Last).Next = 0);
+
+ -- Copy element from Source to Target
+
+ X := Source.First;
+ Append (Target, N (X).Element);
+
+ -- Unlink node of Source
+
+ Source.First := 0;
+ Source.Last := 0;
+ Source.Length := 0;
+
+ -- Return the unlinked node to the free store
+
+ Free (Source, X);
+ end if;
end Move;
----------
@@ -1172,8 +1216,8 @@ package body Ada.Containers.Formal_Doubly_Linked_Lists is
"attempt to tamper with cursors (list is locked)";
end if;
- pragma Assert (Vet (Container, Position),
- "bad cursor in Replace_Element");
+ pragma Assert
+ (Vet (Container, Position), "bad cursor in Replace_Element");
declare
N : Node_Array renames Container.Nodes;
@@ -1372,7 +1416,6 @@ package body Ada.Containers.Formal_Doubly_Linked_Lists is
begin
if Before.Node /= 0 then
- null;
pragma Assert (Vet (Target, Before), "bad cursor in Splice");
end if;
@@ -1464,17 +1507,16 @@ package body Ada.Containers.Formal_Doubly_Linked_Lists is
begin
if Before.Node /= 0 then
- null;
- pragma Assert (Vet (Container, Before),
- "bad Before cursor in Splice");
+ pragma Assert
+ (Vet (Container, Before), "bad Before cursor in Splice");
end if;
if Position.Node = 0 then
raise Constraint_Error with "Position cursor has no element";
end if;
- pragma Assert (Vet (Container, Position),
- "bad Position cursor in Splice");
+ pragma Assert
+ (Vet (Container, Position), "bad Position cursor in Splice");
if Position.Node = Before.Node
or else N (Position.Node).Next = Before.Node
@@ -1683,8 +1725,8 @@ package body Ada.Containers.Formal_Doubly_Linked_Lists is
raise Constraint_Error with "Position cursor has no element";
end if;
- pragma Assert (Vet (Container, Position),
- "bad cursor in Update_Element");
+ pragma Assert
+ (Vet (Container, Position), "bad cursor in Update_Element");
declare
B : Natural renames Container.Busy;
diff --git a/gcc/ada/a-cidlli.adb b/gcc/ada/a-cidlli.adb
index dbdc6de47d4..b74e8e115e4 100644
--- a/gcc/ada/a-cidlli.adb
+++ b/gcc/ada/a-cidlli.adb
@@ -27,23 +27,25 @@
-- This unit was originally developed by Matthew J Heaney. --
------------------------------------------------------------------------------
-with System; use type System.Address;
with Ada.Unchecked_Deallocation;
+with System; use type System.Address;
package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
procedure Free is
new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
- type Iterator is new
- List_Iterator_Interfaces.Reversible_Iterator with record
- Container : List_Access;
- Node : Node_Access;
- end record;
+ type Iterator is new Limited_Controlled and
+ List_Iterator_Interfaces.Reversible_Iterator with
+ record
+ Container : List_Access;
+ Node : Node_Access;
+ end record;
- overriding function First (Object : Iterator) return Cursor;
+ overriding procedure Finalize (Object : in out Iterator);
- overriding function Last (Object : Iterator) return Cursor;
+ overriding function First (Object : Iterator) return Cursor;
+ overriding function Last (Object : Iterator) return Cursor;
overriding function Next
(Object : Iterator;
@@ -429,6 +431,22 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
return Position.Node.Element.all;
end Element;
+ --------------
+ -- Finalize --
+ --------------
+
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -459,7 +477,7 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
while Node /= null loop
if Node.Element.all = Item then
- return Cursor'(Container'Unchecked_Access, Node);
+ return Cursor'(Container'Unrestricted_Access, Node);
end if;
Node := Node.Next;
@@ -478,15 +496,28 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
return No_Element;
end if;
- return Cursor'(Container'Unchecked_Access, Container.First);
+ return Cursor'(Container'Unrestricted_Access, Container.First);
end First;
function First (Object : Iterator) return Cursor is
begin
- if Object.Container = null then
- return No_Element;
+ -- The value of the iterator object's Node component influences the
+ -- behavior of the First (and Last) selector function.
+
+ -- When the Node component is null, this means the iterator object was
+ -- constructed without a start expression, in which case the (forward)
+ -- iteration starts from the (logical) beginning of the entire sequence
+ -- of items (corresponding to Container.First, for a forward iterator).
+
+ -- Otherwise, this is iteration over a partial sequence of items. When
+ -- the Node component is non-null, the iterator object was constructed
+ -- with a start expression, that specifies the position from which the
+ -- (forward) partial iteration begins.
+
+ if Object.Node = null then
+ return Indefinite_Doubly_Linked_Lists.First (Object.Container.all);
else
- return Cursor'(Object.Container, Object.Container.First);
+ return Cursor'(Object.Container, Object.Node);
end if;
end First;
@@ -871,9 +902,7 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
(Container : List;
Process : not null access procedure (Position : Cursor))
is
- C : List renames Container'Unrestricted_Access.all;
- B : Natural renames C.Busy;
-
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
Node : Node_Access := Container.First;
begin
@@ -881,7 +910,7 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
begin
while Node /= null loop
- Process (Cursor'(Container'Unchecked_Access, Node));
+ Process (Cursor'(Container'Unrestricted_Access, Node));
Node := Node.Next;
end loop;
exception
@@ -897,22 +926,75 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
(Container : List)
return List_Iterator_Interfaces.Reversible_Iterator'class
is
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- if Container.Length = 0 then
- return Iterator'(null, null);
- else
- return Iterator'(Container'Unchecked_Access, Container.First);
- end if;
+ -- The value of the Node component influences the behavior of the First
+ -- and Last selector functions of the iterator object. When the Node
+ -- component is null (as is the case here), this means the iterator
+ -- object was constructed without a start expression. This is a
+ -- complete iterator, meaning that the iteration starts from the
+ -- (logical) beginning of the sequence of items.
+
+ -- Note: For a forward iterator, Container.First is the beginning, and
+ -- for a reverse iterator, Container.Last is the beginning.
+
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Node => null)
+ do
+ B := B + 1;
+ end return;
end Iterate;
function Iterate
(Container : List;
Start : Cursor)
- return List_Iterator_Interfaces.Reversible_Iterator'class
+ return List_Iterator_Interfaces.Reversible_Iterator'Class
is
- It : constant Iterator := (Container'Unchecked_Access, Start.Node);
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- return It;
+ -- It was formerly the case that when Start = No_Element, the partial
+ -- iterator was defined to behave the same as for a complete iterator,
+ -- and iterate over the entire sequence of items. However, those
+ -- semantics were unintuitive and arguably error-prone (it is too easy
+ -- to accidentally create an endless loop), and so they were changed,
+ -- per the ARG meeting in Denver on 2011/11. However, there was no
+ -- consensus about what positive meaning this corner case should have,
+ -- and so it was decided to simply raise an exception. This does imply,
+ -- however, that it is not possible to use a partial iterator to specify
+ -- an empty sequence of items.
+
+ if Start = No_Element then
+ raise Constraint_Error with
+ "Start position for iterator equals No_Element";
+ end if;
+
+ if Start.Container /= Container'Unrestricted_Access then
+ raise Program_Error with
+ "Start cursor of Iterate designates wrong list";
+ end if;
+
+ pragma Assert (Vet (Start), "Start cursor of Iterate is bad");
+
+ -- The value of the Node component influences the behavior of the First
+ -- and Last selector functions of the iterator object. When the Node
+ -- component is non-null (as is the case here), it means that this
+ -- is a partial iteration, over a subset of the complete sequence of
+ -- items. The iterator object was constructed with a start expression,
+ -- indicating the position from which the iteration begins. Note that
+ -- the start position has the same value irrespective of whether this
+ -- is a forward or reverse iteration.
+
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Node => Start.Node)
+ do
+ B := B + 1;
+ end return;
end Iterate;
----------
@@ -925,15 +1007,28 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
return No_Element;
end if;
- return Cursor'(Container'Unchecked_Access, Container.Last);
+ return Cursor'(Container'Unrestricted_Access, Container.Last);
end Last;
function Last (Object : Iterator) return Cursor is
begin
- if Object.Container = null then
- return No_Element;
+ -- The value of the iterator object's Node component influences the
+ -- behavior of the Last (and First) selector function.
+
+ -- When the Node component is null, this means the iterator object was
+ -- constructed without a start expression, in which case the (reverse)
+ -- iteration starts from the (logical) beginning of the entire sequence
+ -- (corresponding to Container.Last, for a reverse iterator).
+
+ -- Otherwise, this is iteration over a partial sequence of items. When
+ -- the Node component is non-null, the iterator object was constructed
+ -- with a start expression, that specifies the position from which the
+ -- (reverse) partial iteration begins.
+
+ if Object.Node = null then
+ return Indefinite_Doubly_Linked_Lists.Last (Object.Container.all);
else
- return Cursor'(Object.Container, Object.Container.Last);
+ return Cursor'(Object.Container, Object.Node);
end if;
end Last;
@@ -1016,12 +1111,16 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
function Next (Object : Iterator; Position : Cursor) return Cursor is
begin
- if Position.Node = Object.Container.Last then
+ if Position.Container = null then
return No_Element;
+ end if;
- else
- return (Object.Container, Position.Node.Next);
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Next designates wrong list";
end if;
+
+ return Next (Position);
end Next;
-------------
@@ -1067,11 +1166,16 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
function Previous (Object : Iterator; Position : Cursor) return Cursor is
begin
- if Position.Node = Position.Container.First then
+ if Position.Container = null then
return No_Element;
- else
- return (Object.Container, Position.Node.Prev);
end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Previous designates wrong list";
+ end if;
+
+ return Previous (Position);
end Previous;
-------------------
@@ -1380,7 +1484,7 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
while Node /= null loop
if Node.Element.all = Item then
- return Cursor'(Container'Unchecked_Access, Node);
+ return Cursor'(Container'Unrestricted_Access, Node);
end if;
Node := Node.Prev;
@@ -1407,7 +1511,7 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
begin
while Node /= null loop
- Process (Cursor'(Container'Unchecked_Access, Node));
+ Process (Cursor'(Container'Unrestricted_Access, Node));
Node := Node.Prev;
end loop;
exception
diff --git a/gcc/ada/a-cidlli.ads b/gcc/ada/a-cidlli.ads
index c40ad30b155..be1b4344a8a 100644
--- a/gcc/ada/a-cidlli.ads
+++ b/gcc/ada/a-cidlli.ads
@@ -309,7 +309,7 @@ private
for List'Write use Write;
- type List_Access is access constant List;
+ type List_Access is access all List;
for List_Access'Storage_Size use 0;
type Cursor is
diff --git a/gcc/ada/a-cihama.adb b/gcc/ada/a-cihama.adb
index b90c5426481..e9b9cc05d91 100644
--- a/gcc/ada/a-cihama.adb
+++ b/gcc/ada/a-cihama.adb
@@ -34,7 +34,6 @@ with Ada.Containers.Hash_Tables.Generic_Keys;
pragma Elaborate_All (Ada.Containers.Hash_Tables.Generic_Keys);
with Ada.Unchecked_Deallocation;
-
with System; use type System.Address;
package body Ada.Containers.Indefinite_Hashed_Maps is
@@ -45,11 +44,13 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
procedure Free_Element is
new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
- type Iterator is new
- Map_Iterator_Interfaces.Forward_Iterator with record
- Container : Map_Access;
- Node : Node_Access;
- end record;
+ type Iterator is new Limited_Controlled and
+ Map_Iterator_Interfaces.Forward_Iterator with
+ record
+ Container : Map_Access;
+ end record;
+
+ overriding procedure Finalize (Object : in out Iterator);
overriding function First (Object : Iterator) return Cursor;
@@ -422,6 +423,18 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
HT_Ops.Finalize (Container.HT);
end Finalize;
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.HT.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -434,7 +447,7 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
return No_Element;
end if;
- return Cursor'(Container'Unchecked_Access, Node);
+ return Cursor'(Container'Unrestricted_Access, Node);
end Find;
--------------------
@@ -472,18 +485,12 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
return No_Element;
end if;
- return Cursor'(Container'Unchecked_Access, Node);
+ return Cursor'(Container'Unrestricted_Access, Node);
end First;
function First (Object : Iterator) return Cursor is
- M : constant Map_Access := Object.Container;
- N : constant Node_Access := HT_Ops.First (M.HT);
begin
- if N = null then
- return No_Element;
- else
- return Cursor'(Object.Container.all'Unchecked_Access, N);
- end if;
+ return Object.Container.First;
end First;
----------
@@ -694,10 +701,10 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
procedure Process_Node (Node : Node_Access) is
begin
- Process (Cursor'(Container'Unchecked_Access, Node));
+ Process (Cursor'(Container'Unrestricted_Access, Node));
end Process_Node;
- B : Natural renames Container'Unrestricted_Access.HT.Busy;
+ B : Natural renames Container'Unrestricted_Access.all.HT.Busy;
-- Start of processing Iterate
@@ -715,13 +722,18 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
B := B - 1;
end Iterate;
- function Iterate (Container : Map)
- return Map_Iterator_Interfaces.Forward_Iterator'class
+ function Iterate
+ (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'Class
is
- Node : constant Node_Access := HT_Ops.First (Container.HT);
- It : constant Iterator := (Container'Unrestricted_Access, Node);
+ B : Natural renames Container'Unrestricted_Access.all.HT.Busy;
+
begin
- return It;
+ return It : constant Iterator :=
+ (Limited_Controlled with
+ Container => Container'Unrestricted_Access)
+ do
+ B := B + 1;
+ end return;
end Iterate;
---------
@@ -809,11 +821,16 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
function Next (Object : Iterator; Position : Cursor) return Cursor is
begin
- if Position.Node = null then
+ if Position.Container = null then
return No_Element;
- else
- return (Object.Container, Next (Position).Node);
end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Next designates wrong map";
+ end if;
+
+ return Next (Position);
end Next;
-------------------
diff --git a/gcc/ada/a-cihama.ads b/gcc/ada/a-cihama.ads
index 7c67c315583..3b639f4cff7 100644
--- a/gcc/ada/a-cihama.ads
+++ b/gcc/ada/a-cihama.ads
@@ -341,11 +341,10 @@ private
use HT_Types;
use Ada.Finalization;
- overriding procedure Adjust (Container : in out Map);
-
+ overriding procedure Adjust (Container : in out Map);
overriding procedure Finalize (Container : in out Map);
- type Map_Access is access constant Map;
+ type Map_Access is access all Map;
for Map_Access'Storage_Size use 0;
type Cursor is record
diff --git a/gcc/ada/a-cihase.adb b/gcc/ada/a-cihase.adb
index e29a204570e..3a93f91f5c2 100644
--- a/gcc/ada/a-cihase.adb
+++ b/gcc/ada/a-cihase.adb
@@ -36,16 +36,18 @@ with Ada.Containers.Hash_Tables.Generic_Keys;
pragma Elaborate_All (Ada.Containers.Hash_Tables.Generic_Keys);
with Ada.Containers.Prime_Numbers;
-
-with System; use type System.Address;
+with System; use type System.Address;
package body Ada.Containers.Indefinite_Hashed_Sets is
- type Iterator is new Set_Iterator_Interfaces.Forward_Iterator with record
+ type Iterator is new Limited_Controlled and
+ Set_Iterator_Interfaces.Forward_Iterator with
+ record
Container : Set_Access;
- Position : Cursor;
end record;
+ overriding procedure Finalize (Object : in out Iterator);
+
overriding function First (Object : Iterator) return Cursor;
overriding function Next
@@ -569,6 +571,18 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
HT_Ops.Finalize (Container.HT);
end Finalize;
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.HT.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -649,10 +663,8 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
end First;
function First (Object : Iterator) return Cursor is
- Node : constant Node_Access := HT_Ops.First (Object.Container.HT);
begin
- return (if Node = null then No_Element
- else Cursor'(Object.Container, Node));
+ return Object.Container.First;
end First;
----------
@@ -990,7 +1002,7 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
Process (Cursor'(Container'Unrestricted_Access, Node));
end Process_Node;
- B : Natural renames Container'Unrestricted_Access.HT.Busy;
+ B : Natural renames Container'Unrestricted_Access.all.HT.Busy;
-- Start of processing for Iterate
@@ -1009,9 +1021,17 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
end Iterate;
function Iterate (Container : Set)
- return Set_Iterator_Interfaces.Forward_Iterator'Class is
+ return Set_Iterator_Interfaces.Forward_Iterator'Class
+ is
+ B : Natural renames Container'Unrestricted_Access.all.HT.Busy;
+
begin
- return Iterator'(Container'Unrestricted_Access, First (Container));
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Container'Unrestricted_Access)
+ do
+ B := B + 1;
+ end return;
end Iterate;
------------
@@ -1072,12 +1092,16 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
Position : Cursor) return Cursor
is
begin
+ if Position.Container = null then
+ return No_Element;
+ end if;
+
if Position.Container /= Object.Container then
raise Program_Error with
- "Position cursor designates wrong set";
+ "Position cursor of Next designates wrong set";
end if;
- return (if Position.Node = null then No_Element else Next (Position));
+ return Next (Position);
end Next;
-------------
@@ -1895,7 +1919,7 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
Key_Keys.Delete_Key_Sans_Free (Container.HT, Key, X);
if X = null then
- raise Constraint_Error with "key not in map";
+ raise Constraint_Error with "key not in map"; -- ??? "set"
end if;
Free (X);
@@ -1913,7 +1937,7 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
begin
if Node = null then
- raise Constraint_Error with "key not in map";
+ raise Constraint_Error with "key not in map"; -- ??? "set"
end if;
return Node.Element.all;
diff --git a/gcc/ada/a-cimutr.adb b/gcc/ada/a-cimutr.adb
index 2fdc8a75469..9e211ad156a 100644
--- a/gcc/ada/a-cimutr.adb
+++ b/gcc/ada/a-cimutr.adb
@@ -28,35 +28,41 @@
------------------------------------------------------------------------------
with Ada.Unchecked_Deallocation;
-with System; use type System.Address;
+with System; use type System.Address;
package body Ada.Containers.Indefinite_Multiway_Trees is
- type Iterator is new Tree_Iterator_Interfaces.Forward_Iterator with
+ type Iterator is new Limited_Controlled and
+ Tree_Iterator_Interfaces.Forward_Iterator with
record
Container : Tree_Access;
Position : Cursor;
From_Root : Boolean;
end record;
- type Child_Iterator is new Tree_Iterator_Interfaces.Reversible_Iterator with
+ type Child_Iterator is new Limited_Controlled and
+ Tree_Iterator_Interfaces.Reversible_Iterator with
record
Container : Tree_Access;
Position : Cursor;
end record;
+ overriding procedure Finalize (Object : in out Iterator);
+
overriding function First (Object : Iterator) return Cursor;
overriding function Next
- (Object : Iterator;
+ (Object : Iterator;
Position : Cursor) return Cursor;
+ overriding procedure Finalize (Object : in out Child_Iterator);
+
overriding function First (Object : Child_Iterator) return Cursor;
overriding function Next
- (Object : Child_Iterator;
+ (Object : Child_Iterator;
Position : Cursor) return Cursor;
overriding function Previous
- (Object : Child_Iterator;
+ (Object : Child_Iterator;
Position : Cursor) return Cursor;
overriding function Last (Object : Child_Iterator) return Cursor;
@@ -925,6 +931,34 @@ package body Ada.Containers.Indefinite_Multiway_Trees is
return Equal_Children (Left_Subtree, Right_Subtree);
end Equal_Subtree;
+ --------------
+ -- Finalize --
+ --------------
+
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
+ procedure Finalize (Object : in out Child_Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -1304,8 +1338,7 @@ package body Ada.Containers.Indefinite_Multiway_Trees is
(Container : Tree;
Process : not null access procedure (Position : Cursor))
is
- T : Tree renames Container'Unrestricted_Access.all;
- B : Integer renames T.Busy;
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
begin
B := B + 1;
@@ -1326,13 +1359,19 @@ package body Ada.Containers.Indefinite_Multiway_Trees is
function Iterate (Container : Tree)
return Tree_Iterator_Interfaces.Forward_Iterator'Class
is
- Root_Cursor : constant Cursor :=
- (Container'Unrestricted_Access, Root_Node (Container));
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+ RC : constant Cursor :=
+ (Container'Unrestricted_Access, Root_Node (Container));
+
begin
- return
- Iterator'(Container'Unrestricted_Access,
- First_Child (Root_Cursor),
- From_Root => True);
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Position => First_Child (RC),
+ From_Root => True)
+ do
+ B := B + 1;
+ end return;
end Iterate;
----------------------
@@ -1349,7 +1388,7 @@ package body Ada.Containers.Indefinite_Multiway_Trees is
end if;
declare
- B : Integer renames Parent.Container.Busy;
+ B : Natural renames Parent.Container.Busy;
C : Tree_Node_Access;
begin
@@ -1396,9 +1435,16 @@ package body Ada.Containers.Indefinite_Multiway_Trees is
Parent : Cursor)
return Tree_Iterator_Interfaces.Reversible_Iterator'Class
is
- pragma Unreferenced (Container);
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- return Child_Iterator'(Parent.Container, Parent);
+ return It : constant Child_Iterator :=
+ Child_Iterator'(Limited_Controlled with
+ Container => Parent.Container,
+ Position => Parent)
+ do
+ B := B + 1;
+ end return;
end Iterate_Children;
---------------------
@@ -1409,8 +1455,17 @@ package body Ada.Containers.Indefinite_Multiway_Trees is
(Position : Cursor)
return Tree_Iterator_Interfaces.Forward_Iterator'Class
is
+ B : Natural renames Position.Container'Unrestricted_Access.all.Busy;
+
begin
- return Iterator'(Position.Container, Position, From_Root => False);
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Position.Container,
+ Position => Position,
+ From_Root => False)
+ do
+ B := B + 1;
+ end return;
end Iterate_Subtree;
procedure Iterate_Subtree
@@ -1423,7 +1478,7 @@ package body Ada.Containers.Indefinite_Multiway_Trees is
end if;
declare
- B : Integer renames Position.Container.Busy;
+ B : Natural renames Position.Container.Busy;
begin
B := B + 1;
@@ -1789,8 +1844,8 @@ package body Ada.Containers.Indefinite_Multiway_Trees is
declare
T : Tree renames Position.Container.all'Unrestricted_Access.all;
- B : Integer renames T.Busy;
- L : Integer renames T.Lock;
+ B : Natural renames T.Busy;
+ L : Natural renames T.Lock;
begin
B := B + 1;
@@ -2052,7 +2107,7 @@ package body Ada.Containers.Indefinite_Multiway_Trees is
end if;
declare
- B : Integer renames Parent.Container.Busy;
+ B : Natural renames Parent.Container.Busy;
C : Tree_Node_Access;
begin
@@ -2555,8 +2610,8 @@ package body Ada.Containers.Indefinite_Multiway_Trees is
declare
T : Tree renames Position.Container.all'Unrestricted_Access.all;
- B : Integer renames T.Busy;
- L : Integer renames T.Lock;
+ B : Natural renames T.Busy;
+ L : Natural renames T.Lock;
begin
B := B + 1;
diff --git a/gcc/ada/a-cimutr.ads b/gcc/ada/a-cimutr.ads
index 29be8ca39ea..6d5684d1b35 100644
--- a/gcc/ada/a-cimutr.ads
+++ b/gcc/ada/a-cimutr.ads
@@ -327,8 +327,8 @@ private
type Tree is new Controlled with record
Root : aliased Tree_Node_Type;
- Busy : Integer := 0;
- Lock : Integer := 0;
+ Busy : Natural := 0;
+ Lock : Natural := 0;
Count : Count_Type := 0;
end record;
diff --git a/gcc/ada/a-ciorma.adb b/gcc/ada/a-ciorma.adb
index cd95b9fd5ab..3aa3c17e1c1 100644
--- a/gcc/ada/a-ciorma.adb
+++ b/gcc/ada/a-ciorma.adb
@@ -40,15 +40,17 @@ with System; use type System.Address;
package body Ada.Containers.Indefinite_Ordered_Maps is
pragma Suppress (All_Checks);
- type Iterator is new
- Map_Iterator_Interfaces.Reversible_Iterator with record
- Container : Map_Access;
- Node : Node_Access;
- end record;
+ type Iterator is new Limited_Controlled and
+ Map_Iterator_Interfaces.Reversible_Iterator with
+ record
+ Container : Map_Access;
+ Node : Node_Access;
+ end record;
- overriding function First (Object : Iterator) return Cursor;
+ overriding procedure Finalize (Object : in out Iterator);
- overriding function Last (Object : Iterator) return Cursor;
+ overriding function First (Object : Iterator) return Cursor;
+ overriding function Last (Object : Iterator) return Cursor;
overriding function Next
(Object : Iterator;
@@ -535,6 +537,22 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
end if;
end Exclude;
+ --------------
+ -- Finalize --
+ --------------
+
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Tree.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -558,11 +576,25 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
end First;
function First (Object : Iterator) return Cursor is
- M : constant Map_Access := Object.Container;
- N : constant Node_Access := M.Tree.First;
begin
- return (if N = null then No_Element
- else Cursor'(Object.Container.all'Unchecked_Access, N));
+ -- The value of the iterator object's Node component influences the
+ -- behavior of the First (and Last) selector function.
+
+ -- When the Node component is null, this means the iterator object was
+ -- constructed without a start expression, in which case the (forward)
+ -- iteration starts from the (logical) beginning of the entire sequence
+ -- of items (corresponding to Container.First for a forward iterator).
+
+ -- Otherwise, this is iteration over a partial sequence of items. When
+ -- the Node component is non-null, the iterator object was constructed
+ -- with a start expression, that specifies the position from which the
+ -- (forward) partial iteration begins.
+
+ if Object.Node = null then
+ return Object.Container.First;
+ else
+ return Cursor'(Object.Container, Object.Node);
+ end if;
end First;
-------------------
@@ -571,13 +603,12 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
function First_Element (Container : Map) return Element_Type is
T : Tree_Type renames Container.Tree;
-
begin
if T.First = null then
raise Constraint_Error with "map is empty";
+ else
+ return T.First.Element.all;
end if;
-
- return T.First.Element.all;
end First_Element;
---------------
@@ -586,13 +617,12 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
function First_Key (Container : Map) return Key_Type is
T : Tree_Type renames Container.Tree;
-
begin
if T.First = null then
raise Constraint_Error with "map is empty";
+ else
+ return T.First.Key.all;
end if;
-
- return T.First.Key.all;
end First_Key;
-----------
@@ -845,7 +875,7 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
Process (Cursor'(Container'Unrestricted_Access, Node));
end Process_Node;
- B : Natural renames Container.Tree'Unrestricted_Access.all.Busy;
+ B : Natural renames Container'Unrestricted_Access.all.Tree.Busy;
-- Start of processing for Iterate
@@ -864,22 +894,78 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
end Iterate;
function Iterate
- (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'class
+ (Container : Map) return Map_Iterator_Interfaces.Reversible_Iterator'Class
is
- Node : constant Node_Access := Container.Tree.First;
- It : constant Iterator := (Container'Unrestricted_Access, Node);
+ B : Natural renames Container'Unrestricted_Access.all.Tree.Busy;
+
begin
- return It;
+ -- The value of the Node component influences the behavior of the First
+ -- and Last selector functions of the iterator object. When the Node
+ -- component is null (as is the case here), this means the iterator
+ -- object was constructed without a start expression. This is a complete
+ -- iterator, meaning that the iteration starts from the (logical)
+ -- beginning of the sequence of items.
+
+ -- Note: For a forward iterator, Container.First is the beginning, and
+ -- for a reverse iterator, Container.Last is the beginning.
+
+ return It : constant Iterator :=
+ (Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Node => null)
+ do
+ B := B + 1;
+ end return;
end Iterate;
function Iterate
(Container : Map;
Start : Cursor)
- return Map_Iterator_Interfaces.Reversible_Iterator'class
+ return Map_Iterator_Interfaces.Reversible_Iterator'Class
is
- It : constant Iterator := (Container'Unrestricted_Access, Start.Node);
+ B : Natural renames Container'Unrestricted_Access.all.Tree.Busy;
+
begin
- return It;
+ -- It was formerly the case that when Start = No_Element, the partial
+ -- iterator was defined to behave the same as for a complete iterator,
+ -- and iterate over the entire sequence of items. However, those
+ -- semantics were unintuitive and arguably error-prone (it is too easy
+ -- to accidentally create an endless loop), and so they were changed,
+ -- per the ARG meeting in Denver on 2011/11. However, there was no
+ -- consensus about what positive meaning this corner case should have,
+ -- and so it was decided to simply raise an exception. This does imply,
+ -- however, that it is not possible to use a partial iterator to specify
+ -- an empty sequence of items.
+
+ if Start = No_Element then
+ raise Constraint_Error with
+ "Start position for iterator equals No_Element";
+ end if;
+
+ if Start.Container /= Container'Unrestricted_Access then
+ raise Program_Error with
+ "Start cursor of Iterate designates wrong map";
+ end if;
+
+ pragma Assert (Vet (Container.Tree, Start.Node),
+ "Start cursor of Iterate is bad");
+
+ -- The value of the Node component influences the behavior of the First
+ -- and Last selector functions of the iterator object. When the Node
+ -- component is non-null (as is the case here), it means that this
+ -- is a partial iteration, over a subset of the complete sequence of
+ -- items. The iterator object was constructed with a start expression,
+ -- indicating the position from which the iteration begins. Note that
+ -- the start position has the same value irrespective of whether this
+ -- is a forward or reverse iteration.
+
+ return It : constant Iterator :=
+ (Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Node => Start.Node)
+ do
+ B := B + 1;
+ end return;
end Iterate;
---------
@@ -916,11 +1002,25 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
end Last;
function Last (Object : Iterator) return Cursor is
- M : constant Map_Access := Object.Container;
- N : constant Node_Access := M.Tree.Last;
begin
- return (if N = null then No_Element
- else Cursor'(Object.Container.all'Unchecked_Access, N));
+ -- The value of the iterator object's Node component influences the
+ -- behavior of the Last (and First) selector function.
+
+ -- When the Node component is null, this means the iterator object was
+ -- constructed without a start expression, in which case the (reverse)
+ -- iteration starts from the (logical) beginning of the entire sequence
+ -- (corresponding to Container.Last, for a reverse iterator).
+
+ -- Otherwise, this is iteration over a partial sequence of items. When
+ -- the Node component is non-null, the iterator object was constructed
+ -- with a start expression, that specifies the position from which the
+ -- (reverse) partial iteration begins.
+
+ if Object.Node = null then
+ return Object.Container.Last;
+ else
+ return Cursor'(Object.Container, Object.Node);
+ end if;
end Last;
------------------
@@ -1017,8 +1117,16 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
Position : Cursor) return Cursor
is
begin
- return (if Position.Node = null then No_Element
- else (Object.Container, Tree_Operations.Next (Position.Node)));
+ if Position.Container = null then
+ return No_Element;
+ end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Next designates wrong map";
+ end if;
+
+ return Next (Position);
end Next;
------------
@@ -1065,9 +1173,16 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
Position : Cursor) return Cursor
is
begin
- return
- (if Position.Node = null then No_Element
- else (Object.Container, Tree_Operations.Previous (Position.Node)));
+ if Position.Container = null then
+ return No_Element;
+ end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Previous designates wrong map";
+ end if;
+
+ return Previous (Position);
end Previous;
-------------------
@@ -1490,4 +1605,5 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
begin
raise Program_Error with "attempt to stream reference";
end Write;
+
end Ada.Containers.Indefinite_Ordered_Maps;
diff --git a/gcc/ada/a-ciorma.ads b/gcc/ada/a-ciorma.ads
index 1c19b81161f..f4c1321835e 100644
--- a/gcc/ada/a-ciorma.ads
+++ b/gcc/ada/a-ciorma.ads
@@ -201,14 +201,18 @@ package Ada.Containers.Indefinite_Ordered_Maps is
(Container : Map;
Process : not null access procedure (Position : Cursor));
+ -- The map container supports iteration in both the forward and reverse
+ -- directions, hence these constructor functions return an object that
+ -- supports the Reversible_Iterator interface.
+
function Iterate
(Container : Map)
- return Map_Iterator_Interfaces.Forward_Iterator'class;
+ return Map_Iterator_Interfaces.Reversible_Iterator'Class;
function Iterate
(Container : Map;
Start : Cursor)
- return Map_Iterator_Interfaces.Reversible_Iterator'class;
+ return Map_Iterator_Interfaces.Reversible_Iterator'Class;
private
diff --git a/gcc/ada/a-ciorse.adb b/gcc/ada/a-ciorse.adb
index 56c33cfe670..4d0f3dcbd6a 100644
--- a/gcc/ada/a-ciorse.adb
+++ b/gcc/ada/a-ciorse.adb
@@ -37,20 +37,21 @@ with Ada.Containers.Red_Black_Trees.Generic_Set_Operations;
pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Set_Operations);
with Ada.Unchecked_Deallocation;
-
with System; use type System.Address;
package body Ada.Containers.Indefinite_Ordered_Sets is
- type Iterator is new
- Ordered_Set_Iterator_Interfaces.Reversible_Iterator with record
- Container : access constant Set;
- Node : Node_Access;
- end record;
+ type Iterator is new Limited_Controlled and
+ Set_Iterator_Interfaces.Reversible_Iterator with
+ record
+ Container : Set_Access;
+ Node : Node_Access;
+ end record;
- overriding function First (Object : Iterator) return Cursor;
+ overriding procedure Finalize (Object : in out Iterator);
- overriding function Last (Object : Iterator) return Cursor;
+ overriding function First (Object : Iterator) return Cursor;
+ overriding function Last (Object : Iterator) return Cursor;
overriding function Next
(Object : Iterator;
@@ -571,6 +572,22 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
end if;
end Exclude;
+ --------------
+ -- Finalize --
+ --------------
+
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Tree.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -600,8 +617,24 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
function First (Object : Iterator) return Cursor is
begin
- return Cursor'(
- Object.Container.all'Unrestricted_Access, Object.Container.Tree.First);
+ -- The value of the iterator object's Node component influences the
+ -- behavior of the First (and Last) selector function.
+
+ -- When the Node component is null, this means the iterator object was
+ -- constructed without a start expression, in which case the (forward)
+ -- iteration starts from the (logical) beginning of the entire sequence
+ -- of items (corresponding to Container.First, for a forward iterator).
+
+ -- Otherwise, this is iteration over a partial sequence of items. When
+ -- the Node component is non-null, the iterator object was constructed
+ -- with a start expression, that specifies the position from which the
+ -- (forward) partial iteration begins.
+
+ if Object.Node = null then
+ return Object.Container.First;
+ else
+ return Cursor'(Object.Container, Object.Node);
+ end if;
end First;
-------------------
@@ -1238,7 +1271,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
Process (Cursor'(Container'Unrestricted_Access, Node));
end Process_Node;
- T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+ T : Tree_Type renames Container'Unrestricted_Access.all.Tree;
B : Natural renames T.Busy;
-- Start of processing for Iterate
@@ -1259,22 +1292,78 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
function Iterate
(Container : Set)
- return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
+ return Set_Iterator_Interfaces.Reversible_Iterator'class
is
- It : constant Iterator :=
- (Container'Unchecked_Access, Container.Tree.First);
+ B : Natural renames Container'Unrestricted_Access.all.Tree.Busy;
+
begin
- return It;
+ -- The value of the Node component influences the behavior of the First
+ -- and Last selector functions of the iterator object. When the Node
+ -- component is null (as is the case here), this means the iterator
+ -- object was constructed without a start expression. This is a complete
+ -- iterator, meaning that the iteration starts from the (logical)
+ -- beginning of the sequence of items.
+
+ -- Note: For a forward iterator, Container.First is the beginning, and
+ -- for a reverse iterator, Container.Last is the beginning.
+
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Node => null)
+ do
+ B := B + 1;
+ end return;
end Iterate;
function Iterate
(Container : Set;
Start : Cursor)
- return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
+ return Set_Iterator_Interfaces.Reversible_Iterator'class
is
- It : constant Iterator := (Container'Unchecked_Access, Start.Node);
+ B : Natural renames Container'Unrestricted_Access.all.Tree.Busy;
+
begin
- return It;
+ -- It was formerly the case that when Start = No_Element, the partial
+ -- iterator was defined to behave the same as for a complete iterator,
+ -- and iterate over the entire sequence of items. However, those
+ -- semantics were unintuitive and arguably error-prone (it is too easy
+ -- to accidentally create an endless loop), and so they were changed,
+ -- per the ARG meeting in Denver on 2011/11. However, there was no
+ -- consensus about what positive meaning this corner case should have,
+ -- and so it was decided to simply raise an exception. This does imply,
+ -- however, that it is not possible to use a partial iterator to specify
+ -- an empty sequence of items.
+
+ if Start = No_Element then
+ raise Constraint_Error with
+ "Start position for iterator equals No_Element";
+ end if;
+
+ if Start.Container /= Container'Unrestricted_Access then
+ raise Program_Error with
+ "Start cursor of Iterate designates wrong set";
+ end if;
+
+ pragma Assert (Vet (Container.Tree, Start.Node),
+ "Start cursor of Iterate is bad");
+
+ -- The value of the Node component influences the behavior of the First
+ -- and Last selector functions of the iterator object. When the Node
+ -- component is non-null (as is the case here), it means that this is a
+ -- partial iteration, over a subset of the complete sequence of
+ -- items. The iterator object was constructed with a start expression,
+ -- indicating the position from which the iteration begins. Note that
+ -- the start position has the same value irrespective of whether this is
+ -- a forward or reverse iteration.
+
+ return It : constant Iterator :=
+ (Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Node => Start.Node)
+ do
+ B := B + 1;
+ end return;
end Iterate;
----------
@@ -1290,9 +1379,24 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
function Last (Object : Iterator) return Cursor is
begin
- return (if Object.Container.Tree.Last = null then No_Element
- else Cursor'(Object.Container.all'Unrestricted_Access,
- Object.Container.Tree.Last));
+ -- The value of the iterator object's Node component influences the
+ -- behavior of the Last (and First) selector function.
+
+ -- When the Node component is null, this means the iterator object was
+ -- constructed without a start expression, in which case the (reverse)
+ -- iteration starts from the (logical) beginning of the entire sequence
+ -- (corresponding to Container.Last, for a reverse iterator).
+
+ -- Otherwise, this is iteration over a partial sequence of items. When
+ -- the Node component is non-null, the iterator object was constructed
+ -- with a start expression, that specifies the position from which the
+ -- (reverse) partial iteration begins.
+
+ if Object.Node = null then
+ return Object.Container.Last;
+ else
+ return Cursor'(Object.Container, Object.Node);
+ end if;
end Last;
------------------
@@ -1372,8 +1476,16 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
(Object : Iterator;
Position : Cursor) return Cursor
is
- pragma Unreferenced (Object);
begin
+ if Position.Container = null then
+ return No_Element;
+ end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Next designates wrong set";
+ end if;
+
return Next (Position);
end Next;
@@ -1430,8 +1542,16 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
(Object : Iterator;
Position : Cursor) return Cursor
is
- pragma Unreferenced (Object);
begin
+ if Position.Container = null then
+ return No_Element;
+ end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Previous designates wrong set";
+ end if;
+
return Previous (Position);
end Previous;
diff --git a/gcc/ada/a-ciorse.ads b/gcc/ada/a-ciorse.ads
index c0ead018bb2..ac711246542 100644
--- a/gcc/ada/a-ciorse.ads
+++ b/gcc/ada/a-ciorse.ads
@@ -64,7 +64,7 @@ package Ada.Containers.Indefinite_Ordered_Sets is
function Has_Element (Position : Cursor) return Boolean;
- package Ordered_Set_Iterator_Interfaces is new
+ package Set_Iterator_Interfaces is new
Ada.Iterator_Interfaces (Cursor, Has_Element);
type Constant_Reference_Type
@@ -233,12 +233,12 @@ package Ada.Containers.Indefinite_Ordered_Sets is
function Iterate
(Container : Set)
- return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class;
+ return Set_Iterator_Interfaces.Reversible_Iterator'class;
function Iterate
(Container : Set;
Start : Cursor)
- return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class;
+ return Set_Iterator_Interfaces.Reversible_Iterator'class;
generic
type Key_Type (<>) is private;
diff --git a/gcc/ada/a-cobove.adb b/gcc/ada/a-cobove.adb
index e78e3ce12d3..e570f828bb1 100644
--- a/gcc/ada/a-cobove.adb
+++ b/gcc/ada/a-cobove.adb
@@ -28,16 +28,19 @@
------------------------------------------------------------------------------
with Ada.Containers.Generic_Array_Sort;
-
+with Ada.Finalization; use Ada.Finalization;
with System; use type System.Address;
package body Ada.Containers.Bounded_Vectors is
- type Iterator is new
- Vector_Iterator_Interfaces.Reversible_Iterator with record
- Container : Vector_Access;
- Index : Index_Type;
- end record;
+ type Iterator is new Limited_Controlled and
+ Vector_Iterator_Interfaces.Reversible_Iterator with
+ record
+ Container : Vector_Access;
+ Index : Index_Type;
+ end record;
+
+ overriding procedure Finalize (Object : in out Iterator);
overriding function First (Object : Iterator) return Cursor;
overriding function Last (Object : Iterator) return Cursor;
@@ -658,6 +661,22 @@ package body Ada.Containers.Bounded_Vectors is
end if;
end Element;
+ --------------
+ -- Finalize --
+ --------------
+
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -1607,8 +1626,7 @@ package body Ada.Containers.Bounded_Vectors is
(Container : Vector;
Process : not null access procedure (Position : Cursor))
is
- V : Vector renames Container'Unrestricted_Access.all;
- B : Natural renames V.Busy;
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
begin
B := B + 1;
@@ -1630,8 +1648,16 @@ package body Ada.Containers.Bounded_Vectors is
(Container : Vector)
return Vector_Iterator_Interfaces.Reversible_Iterator'Class
is
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- return Iterator'(Container'Unrestricted_Access, Index_Type'First);
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Index => Index_Type'First)
+ do
+ B := B + 1;
+ end return;
end Iterate;
function Iterate
@@ -1639,8 +1665,16 @@ package body Ada.Containers.Bounded_Vectors is
Start : Cursor)
return Vector_Iterator_Interfaces.Reversible_Iterator'class
is
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- return Iterator'(Container'Unrestricted_Access, Start.Index);
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Index => Start.Index)
+ do
+ B := B + 1;
+ end return;
end Iterate;
----------
diff --git a/gcc/ada/a-cohama.adb b/gcc/ada/a-cohama.adb
index 351030d3a7b..8c92a303076 100644
--- a/gcc/ada/a-cohama.adb
+++ b/gcc/ada/a-cohama.adb
@@ -39,11 +39,13 @@ with System; use type System.Address;
package body Ada.Containers.Hashed_Maps is
- type Iterator is new
- Map_Iterator_Interfaces.Forward_Iterator with record
- Container : Map_Access;
- Node : Node_Access;
- end record;
+ type Iterator is new Limited_Controlled and
+ Map_Iterator_Interfaces.Forward_Iterator with
+ record
+ Container : Map_Access;
+ end record;
+
+ overriding procedure Finalize (Object : in out Iterator);
overriding function First (Object : Iterator) return Cursor;
@@ -386,6 +388,18 @@ package body Ada.Containers.Hashed_Maps is
HT_Ops.Finalize (Container.HT);
end Finalize;
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.HT.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -398,7 +412,7 @@ package body Ada.Containers.Hashed_Maps is
return No_Element;
end if;
- return Cursor'(Container'Unchecked_Access, Node);
+ return Cursor'(Container'Unrestricted_Access, Node);
end Find;
--------------------
@@ -436,18 +450,12 @@ package body Ada.Containers.Hashed_Maps is
return No_Element;
end if;
- return Cursor'(Container'Unchecked_Access, Node);
+ return Cursor'(Container'Unrestricted_Access, Node);
end First;
function First (Object : Iterator) return Cursor is
- M : constant Map_Access := Object.Container;
- N : constant Node_Access := HT_Ops.First (M.HT);
begin
- if N = null then
- return No_Element;
- end if;
-
- return Cursor'(Object.Container.all'Unchecked_Access, N);
+ return Object.Container.First;
end First;
----------
@@ -553,7 +561,7 @@ package body Ada.Containers.Hashed_Maps is
HT_Ops.Reserve_Capacity (HT, HT.Length);
end if;
- Position.Container := Container'Unchecked_Access;
+ Position.Container := Container'Unrestricted_Access;
end Insert;
procedure Insert
@@ -595,7 +603,7 @@ package body Ada.Containers.Hashed_Maps is
HT_Ops.Reserve_Capacity (HT, HT.Length);
end if;
- Position.Container := Container'Unchecked_Access;
+ Position.Container := Container'Unrestricted_Access;
end Insert;
procedure Insert
@@ -645,10 +653,10 @@ package body Ada.Containers.Hashed_Maps is
procedure Process_Node (Node : Node_Access) is
begin
- Process (Cursor'(Container'Unchecked_Access, Node));
+ Process (Cursor'(Container'Unrestricted_Access, Node));
end Process_Node;
- B : Natural renames Container'Unrestricted_Access.HT.Busy;
+ B : Natural renames Container'Unrestricted_Access.all.HT.Busy;
-- Start of processing for Iterate
@@ -667,12 +675,17 @@ package body Ada.Containers.Hashed_Maps is
end Iterate;
function Iterate
- (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'class
+ (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'Class
is
- Node : constant Node_Access := HT_Ops.First (Container.HT);
- It : constant Iterator := (Container'Unrestricted_Access, Node);
+ B : Natural renames Container'Unrestricted_Access.all.HT.Busy;
+
begin
- return It;
+ return It : constant Iterator :=
+ (Limited_Controlled with
+ Container => Container'Unrestricted_Access)
+ do
+ B := B + 1;
+ end return;
end Iterate;
---------
@@ -752,11 +765,16 @@ package body Ada.Containers.Hashed_Maps is
Position : Cursor) return Cursor
is
begin
- if Position.Node = null then
+ if Position.Container = null then
return No_Element;
- else
- return (Object.Container, Next (Position).Node);
end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Next designates wrong map";
+ end if;
+
+ return Next (Position);
end Next;
-------------------
diff --git a/gcc/ada/a-cohama.ads b/gcc/ada/a-cohama.ads
index 5f01994e8ad..93c3504e8d5 100644
--- a/gcc/ada/a-cohama.ads
+++ b/gcc/ada/a-cohama.ads
@@ -384,7 +384,7 @@ private
for Map'Read use Read;
- type Map_Access is access constant Map;
+ type Map_Access is access all Map;
for Map_Access'Storage_Size use 0;
type Cursor is record
diff --git a/gcc/ada/a-cohase.adb b/gcc/ada/a-cohase.adb
index e0b2345234b..fadff195ff5 100644
--- a/gcc/ada/a-cohase.adb
+++ b/gcc/ada/a-cohase.adb
@@ -41,6 +41,17 @@ with System; use type System.Address;
package body Ada.Containers.Hashed_Sets is
+ type Iterator is limited new
+ Set_Iterator_Interfaces.Forward_Iterator with record
+ Container : Set_Access;
+ end record;
+
+ overriding function First (Object : Iterator) return Cursor;
+
+ overriding function Next
+ (Object : Iterator;
+ Position : Cursor) return Cursor;
+
-----------------------
-- Local Subprograms --
-----------------------
@@ -601,6 +612,11 @@ package body Ada.Containers.Hashed_Sets is
return Cursor'(Container'Unrestricted_Access, Node);
end First;
+ function First (Object : Iterator) return Cursor is
+ begin
+ return Object.Container.First;
+ end First;
+
----------
-- Free --
----------
@@ -920,6 +936,13 @@ package body Ada.Containers.Hashed_Sets is
B := B - 1;
end Iterate;
+ function Iterate
+ (Container : Set) return Set_Iterator_Interfaces.Forward_Iterator'Class
+ is
+ begin
+ return Iterator'(Container => Container'Unrestricted_Access);
+ end Iterate;
+
------------
-- Length --
------------
@@ -973,6 +996,23 @@ package body Ada.Containers.Hashed_Sets is
Position := Next (Position);
end Next;
+ function Next
+ (Object : Iterator;
+ Position : Cursor) return Cursor
+ is
+ begin
+ if Position.Container = null then
+ return No_Element;
+ end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Next designates wrong set";
+ end if;
+
+ return Next (Position);
+ end Next;
+
-------------
-- Overlap --
-------------
@@ -1695,7 +1735,7 @@ package body Ada.Containers.Hashed_Sets is
begin
if Node = null then
- raise Constraint_Error with "key not in map";
+ raise Constraint_Error with "key not in map"; -- ??? "set"
end if;
return Node.Element;
diff --git a/gcc/ada/a-cohase.ads b/gcc/ada/a-cohase.ads
index 0bb370bfe83..96944cd2b2f 100644
--- a/gcc/ada/a-cohase.ads
+++ b/gcc/ada/a-cohase.ads
@@ -34,6 +34,7 @@
private with Ada.Containers.Hash_Tables;
private with Ada.Streams;
private with Ada.Finalization;
+with Ada.Iterator_Interfaces;
generic
type Element_Type is private;
@@ -49,7 +50,11 @@ package Ada.Containers.Hashed_Sets is
pragma Preelaborate;
pragma Remote_Types;
- type Set is tagged private;
+ type Set is tagged private
+ with
+ Default_Iterator => Iterate,
+ Iterator_Element => Element_Type;
+
pragma Preelaborable_Initialization (Set);
type Cursor is private;
@@ -63,6 +68,12 @@ package Ada.Containers.Hashed_Sets is
-- Cursor objects declared without an initialization expression are
-- initialized to the value No_Element.
+ function Has_Element (Position : Cursor) return Boolean;
+ -- Equivalent to Position /= No_Element
+
+ package Set_Iterator_Interfaces is new
+ Ada.Iterator_Interfaces (Cursor, Has_Element);
+
function "=" (Left, Right : Set) return Boolean;
-- For each element in Left, set equality attempts to find the equal
-- element in Right; if a search fails, then set equality immediately
@@ -303,9 +314,6 @@ package Ada.Containers.Hashed_Sets is
function Contains (Container : Set; Item : Element_Type) return Boolean;
-- Equivalent to Find (Container, Item) /= No_Element
- function Has_Element (Position : Cursor) return Boolean;
- -- Equivalent to Position /= No_Element
-
function Equivalent_Elements (Left, Right : Cursor) return Boolean;
-- Returns the result of calling Equivalent_Elements with the elements of
-- the nodes designated by cursors Left and Right.
@@ -327,6 +335,9 @@ package Ada.Containers.Hashed_Sets is
Process : not null access procedure (Position : Cursor));
-- Calls Process for each node in the set
+ function Iterate
+ (Container : Set) return Set_Iterator_Interfaces.Forward_Iterator'Class;
+
generic
type Key_Type (<>) is private;
diff --git a/gcc/ada/a-coinve.adb b/gcc/ada/a-coinve.adb
index e35f2f781de..02a3c53e3f2 100644
--- a/gcc/ada/a-coinve.adb
+++ b/gcc/ada/a-coinve.adb
@@ -29,7 +29,7 @@
with Ada.Containers.Generic_Array_Sort;
with Ada.Unchecked_Deallocation;
-with System; use type System.Address;
+with System; use type System.Address;
package body Ada.Containers.Indefinite_Vectors is
@@ -39,15 +39,17 @@ package body Ada.Containers.Indefinite_Vectors is
procedure Free is
new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
- type Iterator is new
- Vector_Iterator_Interfaces.Reversible_Iterator with record
+ type Iterator is new Limited_Controlled and
+ Vector_Iterator_Interfaces.Reversible_Iterator with
+ record
Container : Vector_Access;
Index : Index_Type;
end record;
- overriding function First (Object : Iterator) return Cursor;
+ overriding procedure Finalize (Object : in out Iterator);
- overriding function Last (Object : Iterator) return Cursor;
+ overriding function First (Object : Iterator) return Cursor;
+ overriding function Last (Object : Iterator) return Cursor;
overriding function Next
(Object : Iterator;
@@ -1105,6 +1107,18 @@ package body Ada.Containers.Indefinite_Vectors is
end;
end Finalize;
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -1129,7 +1143,7 @@ package body Ada.Containers.Indefinite_Vectors is
if Container.Elements.EA (J) /= null
and then Container.Elements.EA (J).all = Item
then
- return (Container'Unchecked_Access, J);
+ return (Container'Unrestricted_Access, J);
end if;
end loop;
@@ -1167,7 +1181,7 @@ package body Ada.Containers.Indefinite_Vectors is
return No_Element;
end if;
- return (Container'Unchecked_Access, Index_Type'First);
+ return (Container'Unrestricted_Access, Index_Type'First);
end First;
function First (Object : Iterator) return Cursor is
@@ -1982,7 +1996,7 @@ package body Ada.Containers.Indefinite_Vectors is
begin
if Before.Container /= null
- and then Before.Container /= Container'Unchecked_Access
+ and then Before.Container /= Container'Unrestricted_Access
then
raise Program_Error with "Before cursor denotes wrong container";
end if;
@@ -2018,7 +2032,8 @@ package body Ada.Containers.Indefinite_Vectors is
begin
if Before.Container /= null
- and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
+ and then Before.Container /=
+ Vector_Access'(Container'Unrestricted_Access)
then
raise Program_Error with "Before cursor denotes wrong container";
end if;
@@ -2029,7 +2044,7 @@ package body Ada.Containers.Indefinite_Vectors is
then
Position := No_Element;
else
- Position := (Container'Unchecked_Access, Before.Index);
+ Position := (Container'Unrestricted_Access, Before.Index);
end if;
return;
@@ -2051,7 +2066,7 @@ package body Ada.Containers.Indefinite_Vectors is
Insert (Container, Index, New_Item);
- Position := Cursor'(Container'Unchecked_Access, Index);
+ Position := Cursor'(Container'Unrestricted_Access, Index);
end Insert;
procedure Insert
@@ -2064,7 +2079,7 @@ package body Ada.Containers.Indefinite_Vectors is
begin
if Before.Container /= null
- and then Before.Container /= Container'Unchecked_Access
+ and then Before.Container /= Container'Unrestricted_Access
then
raise Program_Error with "Before cursor denotes wrong container";
end if;
@@ -2101,7 +2116,7 @@ package body Ada.Containers.Indefinite_Vectors is
begin
if Before.Container /= null
- and then Before.Container /= Container'Unchecked_Access
+ and then Before.Container /= Container'Unrestricted_Access
then
raise Program_Error with "Before cursor denotes wrong container";
end if;
@@ -2112,7 +2127,7 @@ package body Ada.Containers.Indefinite_Vectors is
then
Position := No_Element;
else
- Position := (Container'Unchecked_Access, Before.Index);
+ Position := (Container'Unrestricted_Access, Before.Index);
end if;
return;
@@ -2134,7 +2149,7 @@ package body Ada.Containers.Indefinite_Vectors is
Insert (Container, Index, New_Item, Count);
- Position := (Container'Unchecked_Access, Index);
+ Position := (Container'Unrestricted_Access, Index);
end Insert;
------------------
@@ -2465,7 +2480,7 @@ package body Ada.Containers.Indefinite_Vectors is
begin
if Before.Container /= null
- and then Before.Container /= Container'Unchecked_Access
+ and then Before.Container /= Container'Unrestricted_Access
then
raise Program_Error with "Before cursor denotes wrong container";
end if;
@@ -2476,7 +2491,7 @@ package body Ada.Containers.Indefinite_Vectors is
then
Position := No_Element;
else
- Position := (Container'Unchecked_Access, Before.Index);
+ Position := (Container'Unrestricted_Access, Before.Index);
end if;
return;
@@ -2498,7 +2513,7 @@ package body Ada.Containers.Indefinite_Vectors is
Insert_Space (Container, Index, Count);
- Position := Cursor'(Container'Unchecked_Access, Index);
+ Position := Cursor'(Container'Unrestricted_Access, Index);
end Insert_Space;
--------------
@@ -2518,15 +2533,14 @@ package body Ada.Containers.Indefinite_Vectors is
(Container : Vector;
Process : not null access procedure (Position : Cursor))
is
- V : Vector renames Container'Unrestricted_Access.all;
- B : Natural renames V.Busy;
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
begin
B := B + 1;
begin
for Indx in Index_Type'First .. Container.Last loop
- Process (Cursor'(Container'Unchecked_Access, Indx));
+ Process (Cursor'(Container'Unrestricted_Access, Indx));
end loop;
exception
when others =>
@@ -2540,9 +2554,16 @@ package body Ada.Containers.Indefinite_Vectors is
function Iterate (Container : Vector)
return Vector_Iterator_Interfaces.Reversible_Iterator'class
is
- It : constant Iterator := (Container'Unchecked_Access, Index_Type'First);
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- return It;
+ return It : constant Iterator :=
+ (Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Index => Index_Type'First)
+ do
+ B := B + 1;
+ end return;
end Iterate;
function Iterate
@@ -2550,10 +2571,16 @@ package body Ada.Containers.Indefinite_Vectors is
Start : Cursor)
return Vector_Iterator_Interfaces.Reversible_Iterator'class
is
- It : constant Iterator :=
- (Container'Unchecked_Access, Start.Index);
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- return It;
+ return It : constant Iterator :=
+ (Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Index => Start.Index)
+ do
+ B := B + 1;
+ end return;
end Iterate;
----------
@@ -2566,7 +2593,7 @@ package body Ada.Containers.Indefinite_Vectors is
return No_Element;
end if;
- return (Container'Unchecked_Access, Container.Last);
+ return (Container'Unrestricted_Access, Container.Last);
end Last;
function Last (Object : Iterator) return Cursor is
@@ -3313,7 +3340,7 @@ package body Ada.Containers.Indefinite_Vectors is
begin
if Position.Container /= null
- and then Position.Container /= Container'Unchecked_Access
+ and then Position.Container /= Container'Unrestricted_Access
then
raise Program_Error with "Position cursor denotes wrong container";
end if;
@@ -3330,7 +3357,7 @@ package body Ada.Containers.Indefinite_Vectors is
if Container.Elements.EA (Indx) /= null
and then Container.Elements.EA (Indx).all = Item
then
- return (Container'Unchecked_Access, Indx);
+ return (Container'Unrestricted_Access, Indx);
end if;
end loop;
@@ -3376,7 +3403,7 @@ package body Ada.Containers.Indefinite_Vectors is
begin
for Indx in reverse Index_Type'First .. Container.Last loop
- Process (Cursor'(Container'Unchecked_Access, Indx));
+ Process (Cursor'(Container'Unrestricted_Access, Indx));
end loop;
exception
when others =>
@@ -3491,7 +3518,7 @@ package body Ada.Containers.Indefinite_Vectors is
return No_Element;
end if;
- return Cursor'(Container'Unchecked_Access, Index);
+ return Cursor'(Container'Unrestricted_Access, Index);
end To_Cursor;
--------------
diff --git a/gcc/ada/a-coinve.ads b/gcc/ada/a-coinve.ads
index 06568278997..85d68ebf7ee 100644
--- a/gcc/ada/a-coinve.ads
+++ b/gcc/ada/a-coinve.ads
@@ -426,7 +426,7 @@ private
for Vector'Read use Read;
- type Vector_Access is access constant Vector;
+ type Vector_Access is access all Vector;
for Vector_Access'Storage_Size use 0;
type Cursor is record
diff --git a/gcc/ada/a-comutr.adb b/gcc/ada/a-comutr.adb
index 86be79ffc35..e78aaccf957 100644
--- a/gcc/ada/a-comutr.adb
+++ b/gcc/ada/a-comutr.adb
@@ -29,28 +29,34 @@
with Ada.Unchecked_Conversion;
with Ada.Unchecked_Deallocation;
-with System; use type System.Address;
+with System; use type System.Address;
package body Ada.Containers.Multiway_Trees is
- type Iterator is new Tree_Iterator_Interfaces.Forward_Iterator with
+ type Iterator is new Limited_Controlled and
+ Tree_Iterator_Interfaces.Forward_Iterator with
record
Container : Tree_Access;
Position : Cursor;
From_Root : Boolean;
end record;
- type Child_Iterator is new Tree_Iterator_Interfaces.Reversible_Iterator with
+ type Child_Iterator is new Limited_Controlled and
+ Tree_Iterator_Interfaces.Reversible_Iterator with
record
Container : Tree_Access;
Position : Cursor;
end record;
+ overriding procedure Finalize (Object : in out Iterator);
+
overriding function First (Object : Iterator) return Cursor;
overriding function Next
(Object : Iterator;
Position : Cursor) return Cursor;
+ overriding procedure Finalize (Object : in out Child_Iterator);
+
overriding function First (Object : Child_Iterator) return Cursor;
overriding function Next
(Object : Child_Iterator;
@@ -898,6 +904,34 @@ package body Ada.Containers.Multiway_Trees is
return Equal_Children (Left_Subtree, Right_Subtree);
end Equal_Subtree;
+ --------------
+ -- Finalize --
+ --------------
+
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
+ procedure Finalize (Object : in out Child_Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -1342,8 +1376,7 @@ package body Ada.Containers.Multiway_Trees is
(Container : Tree;
Process : not null access procedure (Position : Cursor))
is
- T : Tree renames Container'Unrestricted_Access.all;
- B : Integer renames T.Busy;
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
begin
B := B + 1;
@@ -1364,13 +1397,19 @@ package body Ada.Containers.Multiway_Trees is
function Iterate (Container : Tree)
return Tree_Iterator_Interfaces.Forward_Iterator'Class
is
- Root_Cursor : constant Cursor :=
- (Container'Unrestricted_Access, Root_Node (Container));
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+ RC : constant Cursor :=
+ (Container'Unrestricted_Access, Root_Node (Container));
+
begin
- return
- Iterator'(Container'Unrestricted_Access,
- First_Child (Root_Cursor),
- From_Root => True);
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Position => First_Child (RC),
+ From_Root => True)
+ do
+ B := B + 1;
+ end return;
end Iterate;
----------------------
@@ -1387,7 +1426,7 @@ package body Ada.Containers.Multiway_Trees is
end if;
declare
- B : Integer renames Parent.Container.Busy;
+ B : Natural renames Parent.Container.Busy;
C : Tree_Node_Access;
begin
@@ -1434,9 +1473,16 @@ package body Ada.Containers.Multiway_Trees is
Parent : Cursor)
return Tree_Iterator_Interfaces.Reversible_Iterator'Class
is
- pragma Unreferenced (Container);
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- return Child_Iterator'(Parent.Container, Parent);
+ return It : constant Child_Iterator :=
+ Child_Iterator'(Limited_Controlled with
+ Container => Parent.Container,
+ Position => Parent)
+ do
+ B := B + 1;
+ end return;
end Iterate_Children;
---------------------
@@ -1447,8 +1493,17 @@ package body Ada.Containers.Multiway_Trees is
(Position : Cursor)
return Tree_Iterator_Interfaces.Forward_Iterator'Class
is
+ B : Natural renames Position.Container'Unrestricted_Access.all.Busy;
+
begin
- return Iterator'(Position.Container, Position, From_Root => False);
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Position.Container,
+ Position => Position,
+ From_Root => False)
+ do
+ B := B + 1;
+ end return;
end Iterate_Subtree;
procedure Iterate_Subtree
@@ -1461,7 +1516,7 @@ package body Ada.Containers.Multiway_Trees is
end if;
declare
- B : Integer renames Position.Container.Busy;
+ B : Natural renames Position.Container.Busy;
begin
B := B + 1;
@@ -1807,8 +1862,8 @@ package body Ada.Containers.Multiway_Trees is
declare
T : Tree renames Position.Container.all'Unrestricted_Access.all;
- B : Integer renames T.Busy;
- L : Integer renames T.Lock;
+ B : Natural renames T.Busy;
+ L : Natural renames T.Lock;
begin
B := B + 1;
@@ -2060,7 +2115,7 @@ package body Ada.Containers.Multiway_Trees is
end if;
declare
- B : Integer renames Parent.Container.Busy;
+ B : Natural renames Parent.Container.Busy;
C : Tree_Node_Access;
begin
@@ -2578,8 +2633,8 @@ package body Ada.Containers.Multiway_Trees is
declare
T : Tree renames Position.Container.all'Unrestricted_Access.all;
- B : Integer renames T.Busy;
- L : Integer renames T.Lock;
+ B : Natural renames T.Busy;
+ L : Natural renames T.Lock;
begin
B := B + 1;
diff --git a/gcc/ada/a-comutr.ads b/gcc/ada/a-comutr.ads
index b035e1637fe..37e2eda0c2c 100644
--- a/gcc/ada/a-comutr.ads
+++ b/gcc/ada/a-comutr.ads
@@ -372,8 +372,8 @@ private
type Tree is new Controlled with record
Root : aliased Root_Node_Type;
- Busy : Integer := 0;
- Lock : Integer := 0;
+ Busy : Natural := 0;
+ Lock : Natural := 0;
Count : Count_Type := 0;
end record;
diff --git a/gcc/ada/a-convec.adb b/gcc/ada/a-convec.adb
index 79071810182..a94f11c9f93 100644
--- a/gcc/ada/a-convec.adb
+++ b/gcc/ada/a-convec.adb
@@ -29,7 +29,6 @@
with Ada.Containers.Generic_Array_Sort;
with Ada.Unchecked_Deallocation;
-
with System; use type System.Address;
package body Ada.Containers.Vectors is
@@ -37,12 +36,15 @@ package body Ada.Containers.Vectors is
procedure Free is
new Ada.Unchecked_Deallocation (Elements_Type, Elements_Access);
- type Iterator is new Vector_Iterator_Interfaces.Reversible_Iterator with
+ type Iterator is new Limited_Controlled and
+ Vector_Iterator_Interfaces.Reversible_Iterator with
record
Container : Vector_Access;
Index : Index_Type;
end record;
+ overriding procedure Finalize (Object : in out Iterator);
+
overriding function First (Object : Iterator) return Cursor;
overriding function Last (Object : Iterator) return Cursor;
overriding function Next
@@ -778,6 +780,18 @@ package body Ada.Containers.Vectors is
Free (X);
end Finalize;
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -800,7 +814,7 @@ package body Ada.Containers.Vectors is
for J in Position.Index .. Container.Last loop
if Container.Elements.EA (J) = Item then
- return (Container'Unchecked_Access, J);
+ return (Container'Unrestricted_Access, J);
end if;
end loop;
@@ -835,7 +849,7 @@ package body Ada.Containers.Vectors is
if Is_Empty (Container) then
return No_Element;
else
- return (Container'Unchecked_Access, Index_Type'First);
+ return (Container'Unrestricted_Access, Index_Type'First);
end if;
end First;
@@ -1500,7 +1514,7 @@ package body Ada.Containers.Vectors is
begin
if Before.Container /= null
- and then Before.Container /= Container'Unchecked_Access
+ and then Before.Container /= Container'Unrestricted_Access
then
raise Program_Error with "Before cursor denotes wrong container";
end if;
@@ -1536,7 +1550,7 @@ package body Ada.Containers.Vectors is
begin
if Before.Container /= null
- and then Before.Container /= Container'Unchecked_Access
+ and then Before.Container /= Container'Unrestricted_Access
then
raise Program_Error with "Before cursor denotes wrong container";
end if;
@@ -1547,7 +1561,7 @@ package body Ada.Containers.Vectors is
then
Position := No_Element;
else
- Position := (Container'Unchecked_Access, Before.Index);
+ Position := (Container'Unrestricted_Access, Before.Index);
end if;
return;
@@ -1569,7 +1583,7 @@ package body Ada.Containers.Vectors is
Insert (Container, Index, New_Item);
- Position := (Container'Unchecked_Access, Index);
+ Position := (Container'Unrestricted_Access, Index);
end Insert;
procedure Insert
@@ -1582,7 +1596,7 @@ package body Ada.Containers.Vectors is
begin
if Before.Container /= null
- and then Before.Container /= Container'Unchecked_Access
+ and then Before.Container /= Container'Unrestricted_Access
then
raise Program_Error with "Before cursor denotes wrong container";
end if;
@@ -1619,7 +1633,7 @@ package body Ada.Containers.Vectors is
begin
if Before.Container /= null
- and then Before.Container /= Container'Unchecked_Access
+ and then Before.Container /= Container'Unrestricted_Access
then
raise Program_Error with "Before cursor denotes wrong container";
end if;
@@ -1630,7 +1644,7 @@ package body Ada.Containers.Vectors is
then
Position := No_Element;
else
- Position := (Container'Unchecked_Access, Before.Index);
+ Position := (Container'Unrestricted_Access, Before.Index);
end if;
return;
@@ -1652,7 +1666,7 @@ package body Ada.Containers.Vectors is
Insert (Container, Index, New_Item, Count);
- Position := (Container'Unchecked_Access, Index);
+ Position := (Container'Unrestricted_Access, Index);
end Insert;
procedure Insert
@@ -2036,7 +2050,7 @@ package body Ada.Containers.Vectors is
begin
if Before.Container /= null
- and then Before.Container /= Container'Unchecked_Access
+ and then Before.Container /= Container'Unrestricted_Access
then
raise Program_Error with "Before cursor denotes wrong container";
end if;
@@ -2047,7 +2061,7 @@ package body Ada.Containers.Vectors is
then
Position := No_Element;
else
- Position := (Container'Unchecked_Access, Before.Index);
+ Position := (Container'Unrestricted_Access, Before.Index);
end if;
return;
@@ -2069,7 +2083,7 @@ package body Ada.Containers.Vectors is
Insert_Space (Container, Index, Count => Count);
- Position := (Container'Unchecked_Access, Index);
+ Position := (Container'Unrestricted_Access, Index);
end Insert_Space;
--------------
@@ -2089,15 +2103,14 @@ package body Ada.Containers.Vectors is
(Container : Vector;
Process : not null access procedure (Position : Cursor))
is
- V : Vector renames Container'Unrestricted_Access.all;
- B : Natural renames V.Busy;
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
begin
B := B + 1;
begin
for Indx in Index_Type'First .. Container.Last loop
- Process (Cursor'(Container'Unchecked_Access, Indx));
+ Process (Cursor'(Container'Unrestricted_Access, Indx));
end loop;
exception
when others =>
@@ -2112,9 +2125,16 @@ package body Ada.Containers.Vectors is
(Container : Vector)
return Vector_Iterator_Interfaces.Reversible_Iterator'Class
is
- It : constant Iterator := (Container'Unchecked_Access, Index_Type'First);
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- return It;
+ return It : constant Iterator :=
+ (Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Index => Index_Type'First)
+ do
+ B := B + 1;
+ end return;
end Iterate;
function Iterate
@@ -2122,9 +2142,16 @@ package body Ada.Containers.Vectors is
Start : Cursor)
return Vector_Iterator_Interfaces.Reversible_Iterator'class
is
- It : constant Iterator := (Container'Unchecked_Access, Start.Index);
+ B : Natural renames Container'Unrestricted_Access.all.Busy;
+
begin
- return It;
+ return It : constant Iterator :=
+ (Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Index => Start.Index)
+ do
+ B := B + 1;
+ end return;
end Iterate;
----------
@@ -2136,7 +2163,7 @@ package body Ada.Containers.Vectors is
if Is_Empty (Container) then
return No_Element;
else
- return (Container'Unchecked_Access, Container.Last);
+ return (Container'Unrestricted_Access, Container.Last);
end if;
end Last;
@@ -2903,7 +2930,7 @@ package body Ada.Containers.Vectors is
begin
if Position.Container /= null
- and then Position.Container /= Container'Unchecked_Access
+ and then Position.Container /= Container'Unrestricted_Access
then
raise Program_Error with "Position cursor denotes wrong container";
end if;
@@ -2915,7 +2942,7 @@ package body Ada.Containers.Vectors is
for Indx in reverse Index_Type'First .. Last loop
if Container.Elements.EA (Indx) = Item then
- return (Container'Unchecked_Access, Indx);
+ return (Container'Unrestricted_Access, Indx);
end if;
end loop;
@@ -2960,7 +2987,7 @@ package body Ada.Containers.Vectors is
begin
for Indx in reverse Index_Type'First .. Container.Last loop
- Process (Cursor'(Container'Unchecked_Access, Indx));
+ Process (Cursor'(Container'Unrestricted_Access, Indx));
end loop;
exception
when others =>
@@ -3061,7 +3088,7 @@ package body Ada.Containers.Vectors is
if Index not in Index_Type'First .. Container.Last then
return No_Element;
else
- return (Container'Unchecked_Access, Index);
+ return (Container'Unrestricted_Access, Index);
end if;
end To_Cursor;
diff --git a/gcc/ada/a-convec.ads b/gcc/ada/a-convec.ads
index 9eb82c791fe..00f9b2abbac 100644
--- a/gcc/ada/a-convec.ads
+++ b/gcc/ada/a-convec.ads
@@ -410,7 +410,7 @@ private
Lock : Natural := 0;
end record;
- type Vector_Access is access constant Vector;
+ type Vector_Access is access all Vector;
for Vector_Access'Storage_Size use 0;
type Cursor is record
diff --git a/gcc/ada/a-coorma.adb b/gcc/ada/a-coorma.adb
index e8099c3c297..778d223e291 100644
--- a/gcc/ada/a-coorma.adb
+++ b/gcc/ada/a-coorma.adb
@@ -39,15 +39,17 @@ with System; use type System.Address;
package body Ada.Containers.Ordered_Maps is
- type Iterator is new
- Map_Iterator_Interfaces.Reversible_Iterator with record
- Container : Map_Access;
- Node : Node_Access;
- end record;
+ type Iterator is new Limited_Controlled and
+ Map_Iterator_Interfaces.Reversible_Iterator with
+ record
+ Container : Map_Access;
+ Node : Node_Access;
+ end record;
- overriding function First (Object : Iterator) return Cursor;
+ overriding procedure Finalize (Object : in out Iterator);
- overriding function Last (Object : Iterator) return Cursor;
+ overriding function First (Object : Iterator) return Cursor;
+ overriding function Last (Object : Iterator) return Cursor;
overriding function Next
(Object : Iterator;
@@ -488,6 +490,22 @@ package body Ada.Containers.Ordered_Maps is
end if;
end Exclude;
+ --------------
+ -- Finalize --
+ --------------
+
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Tree.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -518,13 +536,24 @@ package body Ada.Containers.Ordered_Maps is
end First;
function First (Object : Iterator) return Cursor is
- M : constant Map_Access := Object.Container;
- N : constant Node_Access := M.Tree.First;
begin
- if N = null then
- return No_Element;
+ -- The value of the iterator object's Node component influences the
+ -- behavior of the First (and Last) selector function.
+
+ -- When the Node component is null, this means the iterator object was
+ -- constructed without a start expression, in which case the (forward)
+ -- iteration starts from the (logical) beginning of the entire sequence
+ -- of items (corresponding to Container.First, for a forward iterator).
+
+ -- Otherwise, this is iteration over a partial sequence of items. When
+ -- the Node component is non-null, the iterator object was constructed
+ -- with a start expression, that specifies the position from which the
+ -- (forward) partial iteration begins.
+
+ if Object.Node = null then
+ return Object.Container.First;
else
- return Cursor'(Object.Container.all'Unchecked_Access, N);
+ return Cursor'(Object.Container, Object.Node);
end if;
end First;
@@ -534,7 +563,6 @@ package body Ada.Containers.Ordered_Maps is
function First_Element (Container : Map) return Element_Type is
T : Tree_Type renames Container.Tree;
-
begin
if T.First = null then
raise Constraint_Error with "map is empty";
@@ -827,21 +855,76 @@ package body Ada.Containers.Ordered_Maps is
end Iterate;
function Iterate
- (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'class
+ (Container : Map) return Map_Iterator_Interfaces.Reversible_Iterator'Class
is
- Node : constant Node_Access := Container.Tree.First;
- It : constant Iterator := (Container'Unrestricted_Access, Node);
+ B : Natural renames Container.Tree'Unrestricted_Access.all.Busy;
begin
- return It;
+ -- The value of the Node component influences the behavior of the First
+ -- and Last selector functions of the iterator object. When the Node
+ -- component is null (as is the case here), this means the iterator
+ -- object was constructed without a start expression. This is a
+ -- complete iterator, meaning that the iteration starts from the
+ -- (logical) beginning of the sequence of items.
+
+ -- Note: For a forward iterator, Container.First is the beginning, and
+ -- for a reverse iterator, Container.Last is the beginning.
+
+ return It : constant Iterator :=
+ (Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Node => null)
+ do
+ B := B + 1;
+ end return;
end Iterate;
function Iterate (Container : Map; Start : Cursor)
- return Map_Iterator_Interfaces.Reversible_Iterator'class
+ return Map_Iterator_Interfaces.Reversible_Iterator'Class
is
- It : constant Iterator := (Container'Unrestricted_Access, Start.Node);
+ B : Natural renames Container.Tree'Unrestricted_Access.all.Busy;
+
begin
- return It;
+ -- It was formerly the case that when Start = No_Element, the partial
+ -- iterator was defined to behave the same as for a complete iterator,
+ -- and iterate over the entire sequence of items. However, those
+ -- semantics were unintuitive and arguably error-prone (it is too easy
+ -- to accidentally create an endless loop), and so they were changed,
+ -- per the ARG meeting in Denver on 2011/11. However, there was no
+ -- consensus about what positive meaning this corner case should have,
+ -- and so it was decided to simply raise an exception. This does imply,
+ -- however, that it is not possible to use a partial iterator to specify
+ -- an empty sequence of items.
+
+ if Start = No_Element then
+ raise Constraint_Error with
+ "Start position for iterator equals No_Element";
+ end if;
+
+ if Start.Container /= Container'Unrestricted_Access then
+ raise Program_Error with
+ "Start cursor of Iterate designates wrong map";
+ end if;
+
+ pragma Assert (Vet (Container.Tree, Start.Node),
+ "Start cursor of Iterate is bad");
+
+ -- The value of the Node component influences the behavior of the First
+ -- and Last selector functions of the iterator object. When the Node
+ -- component is non-null (as is the case here), it means that this
+ -- is a partial iteration, over a subset of the complete sequence of
+ -- items. The iterator object was constructed with a start expression,
+ -- indicating the position from which the iteration begins. Note that
+ -- the start position has the same value irrespective of whether this
+ -- is a forward or reverse iteration.
+
+ return It : constant Iterator :=
+ (Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Node => Start.Node)
+ do
+ B := B + 1;
+ end return;
end Iterate;
---------
@@ -876,13 +959,24 @@ package body Ada.Containers.Ordered_Maps is
end Last;
function Last (Object : Iterator) return Cursor is
- M : constant Map_Access := Object.Container;
- N : constant Node_Access := M.Tree.Last;
begin
- if N = null then
- return No_Element;
+ -- The value of the iterator object's Node component influences the
+ -- behavior of the Last (and First) selector function.
+
+ -- When the Node component is null, this means the iterator object was
+ -- constructed without a start expression, in which case the (reverse)
+ -- iteration starts from the (logical) beginning of the entire sequence
+ -- (corresponding to Container.Last, for a reverse iterator).
+
+ -- Otherwise, this is iteration over a partial sequence of items. When
+ -- the Node component is non-null, the iterator object was constructed
+ -- with a start expression, that specifies the position from which the
+ -- (reverse) partial iteration begins.
+
+ if Object.Node = null then
+ return Object.Container.Last;
else
- return Cursor'(Object.Container.all'Unchecked_Access, N);
+ return Cursor'(Object.Container, Object.Node);
end if;
end Last;
@@ -980,11 +1074,16 @@ package body Ada.Containers.Ordered_Maps is
Position : Cursor) return Cursor
is
begin
- if Position.Node = null then
+ if Position.Container = null then
return No_Element;
- else
- return (Object.Container, Tree_Operations.Next (Position.Node));
end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Next designates wrong map";
+ end if;
+
+ return Next (Position);
end Next;
------------
@@ -1032,12 +1131,18 @@ package body Ada.Containers.Ordered_Maps is
Position : Cursor) return Cursor
is
begin
- if Position.Node = null then
+ if Position.Container = null then
return No_Element;
- else
- return (Object.Container, Tree_Operations.Previous (Position.Node));
end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Previous designates wrong map";
+ end if;
+
+ return Previous (Position);
end Previous;
+
-------------------
-- Query_Element --
-------------------
diff --git a/gcc/ada/a-coorma.ads b/gcc/ada/a-coorma.ads
index 53942b71fa2..9d2737a5efb 100644
--- a/gcc/ada/a-coorma.ads
+++ b/gcc/ada/a-coorma.ads
@@ -203,19 +203,23 @@ package Ada.Containers.Ordered_Maps is
(Container : Map;
Process : not null access procedure (Position : Cursor));
+ procedure Reverse_Iterate
+ (Container : Map;
+ Process : not null access procedure (Position : Cursor));
+
+ -- The map container supports iteration in both the forward and reverse
+ -- directions, hence these constructor functions return an object that
+ -- supports the Reversible_Iterator interface.
+
function Iterate
(Container : Map)
- return Map_Iterator_Interfaces.Forward_Iterator'class;
+ return Map_Iterator_Interfaces.Reversible_Iterator'class;
function Iterate
(Container : Map;
Start : Cursor)
return Map_Iterator_Interfaces.Reversible_Iterator'class;
- procedure Reverse_Iterate
- (Container : Map;
- Process : not null access procedure (Position : Cursor));
-
private
pragma Inline (Next);
diff --git a/gcc/ada/a-coorse.adb b/gcc/ada/a-coorse.adb
index 4c6476864b8..b4518f40b75 100644
--- a/gcc/ada/a-coorse.adb
+++ b/gcc/ada/a-coorse.adb
@@ -42,15 +42,17 @@ with System; use type System.Address;
package body Ada.Containers.Ordered_Sets is
- type Iterator is new
- Ordered_Set_Iterator_Interfaces.Reversible_Iterator with record
- Container : access constant Set;
- Node : Node_Access;
- end record;
+ type Iterator is new Limited_Controlled and
+ Set_Iterator_Interfaces.Reversible_Iterator with
+ record
+ Container : Set_Access;
+ Node : Node_Access;
+ end record;
- overriding function First (Object : Iterator) return Cursor;
+ overriding procedure Finalize (Object : in out Iterator);
- overriding function Last (Object : Iterator) return Cursor;
+ overriding function First (Object : Iterator) return Cursor;
+ overriding function Last (Object : Iterator) return Cursor;
overriding function Next
(Object : Iterator;
@@ -512,6 +514,22 @@ package body Ada.Containers.Ordered_Sets is
end if;
end Exclude;
+ --------------
+ -- Finalize --
+ --------------
+
+ procedure Finalize (Object : in out Iterator) is
+ begin
+ if Object.Container /= null then
+ declare
+ B : Natural renames Object.Container.all.Tree.Busy;
+
+ begin
+ B := B - 1;
+ end;
+ end if;
+ end Finalize;
+
----------
-- Find --
----------
@@ -537,9 +555,24 @@ package body Ada.Containers.Ordered_Sets is
function First (Object : Iterator) return Cursor is
begin
- return (if Object.Container = null then No_Element
- else Cursor'(Object.Container.all'Unrestricted_Access,
- Object.Container.Tree.First));
+ -- The value of the iterator object's Node component influences the
+ -- behavior of the First (and Last) selector function.
+
+ -- When the Node component is null, this means the iterator object was
+ -- constructed without a start expression, in which case the (forward)
+ -- iteration starts from the (logical) beginning of the entire sequence
+ -- of items (corresponding to Container.First, for a forward iterator).
+
+ -- Otherwise, this is iteration over a partial sequence of items. When
+ -- the Node component is non-null, the iterator object was constructed
+ -- with a start expression, that specifies the position from which the
+ -- (forward) partial iteration begins.
+
+ if Object.Node = null then
+ return Object.Container.First;
+ else
+ return Cursor'(Object.Container, Object.Node);
+ end if;
end First;
-------------------
@@ -1145,7 +1178,7 @@ package body Ada.Containers.Ordered_Sets is
Process (Cursor'(Container'Unrestricted_Access, Node));
end Process_Node;
- T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+ T : Tree_Type renames Container'Unrestricted_Access.all.Tree;
B : Natural renames T.Busy;
-- Start of processing for Iterate
@@ -1165,22 +1198,74 @@ package body Ada.Containers.Ordered_Sets is
end Iterate;
function Iterate (Container : Set)
- return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
+ return Set_Iterator_Interfaces.Reversible_Iterator'Class
is
+ B : Natural renames Container'Unrestricted_Access.all.Tree.Busy;
+
begin
- if Container.Length = 0 then
- return Iterator'(null, null);
- else
- return Iterator'(Container'Unchecked_Access, Container.Tree.First);
- end if;
+ -- The value of the Node component influences the behavior of the First
+ -- and Last selector functions of the iterator object. When the Node
+ -- component is null (as is the case here), this means the iterator
+ -- object was constructed without a start expression. This is a complete
+ -- iterator, meaning that the iteration starts from the (logical)
+ -- beginning of the sequence of items.
+
+ -- Note: For a forward iterator, Container.First is the beginning, and
+ -- for a reverse iterator, Container.Last is the beginning.
+
+ B := B + 1;
+
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Node => null);
end Iterate;
function Iterate (Container : Set; Start : Cursor)
- return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
+ return Set_Iterator_Interfaces.Reversible_Iterator'Class
is
- It : constant Iterator := (Container'Unchecked_Access, Start.Node);
+ B : Natural renames Container'Unrestricted_Access.all.Tree.Busy;
+
begin
- return It;
+ -- It was formerly the case that when Start = No_Element, the partial
+ -- iterator was defined to behave the same as for a complete iterator,
+ -- and iterate over the entire sequence of items. However, those
+ -- semantics were unintuitive and arguably error-prone (it is too easy
+ -- to accidentally create an endless loop), and so they were changed,
+ -- per the ARG meeting in Denver on 2011/11. However, there was no
+ -- consensus about what positive meaning this corner case should have,
+ -- and so it was decided to simply raise an exception. This does imply,
+ -- however, that it is not possible to use a partial iterator to specify
+ -- an empty sequence of items.
+
+ if Start = No_Element then
+ raise Constraint_Error with
+ "Start position for iterator equals No_Element";
+ end if;
+
+ if Start.Container /= Container'Unrestricted_Access then
+ raise Program_Error with
+ "Start cursor of Iterate designates wrong set";
+ end if;
+
+ pragma Assert (Vet (Container.Tree, Start.Node),
+ "Start cursor of Iterate is bad");
+
+ -- The value of the Node component influences the behavior of the First
+ -- and Last selector functions of the iterator object. When the Node
+ -- component is non-null (as is the case here), it means that this is a
+ -- partial iteration, over a subset of the complete sequence of
+ -- items. The iterator object was constructed with a start expression,
+ -- indicating the position from which the iteration begins. Note that
+ -- the start position has the same value irrespective of whether this is
+ -- a forward or reverse iteration.
+
+ B := B + 1;
+
+ return It : constant Iterator :=
+ Iterator'(Limited_Controlled with
+ Container => Container'Unrestricted_Access,
+ Node => Start.Node);
end Iterate;
----------
@@ -1196,9 +1281,24 @@ package body Ada.Containers.Ordered_Sets is
function Last (Object : Iterator) return Cursor is
begin
- return (if Object.Container = null then No_Element
- else Cursor'(Object.Container.all'Unrestricted_Access,
- Object.Container.Tree.Last));
+ -- The value of the iterator object's Node component influences the
+ -- behavior of the Last (and First) selector function.
+
+ -- When the Node component is null, this means the iterator object was
+ -- constructed without a start expression, in which case the (reverse)
+ -- iteration starts from the (logical) beginning of the entire sequence
+ -- (corresponding to Container.Last, for a reverse iterator).
+
+ -- Otherwise, this is iteration over a partial sequence of items. When
+ -- the Node component is non-null, the iterator object was constructed
+ -- with a start expression, that specifies the position from which the
+ -- (reverse) partial iteration begins.
+
+ if Object.Node = null then
+ return Object.Container.Last;
+ else
+ return Cursor'(Object.Container, Object.Node);
+ end if;
end Last;
------------------
@@ -1271,8 +1371,16 @@ package body Ada.Containers.Ordered_Sets is
end Next;
function Next (Object : Iterator; Position : Cursor) return Cursor is
- pragma Unreferenced (Object);
begin
+ if Position.Container = null then
+ return No_Element;
+ end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Next designates wrong set";
+ end if;
+
return Next (Position);
end Next;
@@ -1322,8 +1430,16 @@ package body Ada.Containers.Ordered_Sets is
end Previous;
function Previous (Object : Iterator; Position : Cursor) return Cursor is
- pragma Unreferenced (Object);
begin
+ if Position.Container = null then
+ return No_Element;
+ end if;
+
+ if Position.Container /= Object.Container then
+ raise Program_Error with
+ "Position cursor of Previous designates wrong set";
+ end if;
+
return Previous (Position);
end Previous;
diff --git a/gcc/ada/a-coorse.ads b/gcc/ada/a-coorse.ads
index 45e6ab90a73..39f69f5eff0 100644
--- a/gcc/ada/a-coorse.ads
+++ b/gcc/ada/a-coorse.ads
@@ -65,7 +65,7 @@ package Ada.Containers.Ordered_Sets is
No_Element : constant Cursor;
- package Ordered_Set_Iterator_Interfaces is new
+ package Set_Iterator_Interfaces is new
Ada.Iterator_Interfaces (Cursor, Has_Element);
type Constant_Reference_Type
@@ -227,12 +227,12 @@ package Ada.Containers.Ordered_Sets is
function Iterate
(Container : Set)
- return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class;
+ return Set_Iterator_Interfaces.Reversible_Iterator'class;
function Iterate
(Container : Set;
Start : Cursor)
- return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class;
+ return Set_Iterator_Interfaces.Reversible_Iterator'class;
generic
type Key_Type (<>) is private;
diff --git a/gcc/ada/a-exetim-posix.adb b/gcc/ada/a-exetim-posix.adb
index 65b21d61d7a..094f2aab51f 100644
--- a/gcc/ada/a-exetim-posix.adb
+++ b/gcc/ada/a-exetim-posix.adb
@@ -34,6 +34,7 @@
with Ada.Task_Identification; use Ada.Task_Identification;
with Ada.Unchecked_Conversion;
+with System.OS_Constants; use System.OS_Constants;
with System.OS_Interface; use System.OS_Interface;
with Interfaces.C; use Interfaces.C;
@@ -112,9 +113,6 @@ package body Ada.Execution_Time is
pragma Import (C, clock_gettime, "clock_gettime");
-- Function from the POSIX.1b Realtime Extensions library
- CLOCK_THREAD_CPUTIME_ID : constant := 3;
- -- Identifier for the clock returning per-task CPU time
-
begin
if T = Ada.Task_Identification.Null_Task_Id then
raise Program_Error;
diff --git a/gcc/ada/a-finali.ads b/gcc/ada/a-finali.ads
index d5cada210e2..b53fd2a8784 100644
--- a/gcc/ada/a-finali.ads
+++ b/gcc/ada/a-finali.ads
@@ -34,14 +34,16 @@
------------------------------------------------------------------------------
pragma Warnings (Off);
--- System.Finalization_Root does not have category Remote_Types, but we
--- allow it anyway.
with System.Finalization_Root;
pragma Warnings (On);
package Ada.Finalization is
+ pragma Pure_12;
+ -- Ada.Finalization is declared pure in Ada 2012 (AI05-0212)
+
pragma Preelaborate;
pragma Remote_Types;
+ -- The above apply in versions of Ada before Ada 2012
type Controlled is abstract tagged private;
pragma Preelaborable_Initialization (Controlled);
diff --git a/gcc/ada/adaint.c b/gcc/ada/adaint.c
index 7e701f53c14..dde33429575 100644
--- a/gcc/ada/adaint.c
+++ b/gcc/ada/adaint.c
@@ -2449,6 +2449,14 @@ __gnat_dup2 (int oldfd, int newfd)
/* Not supported on VxWorks 5.x, but supported on VxWorks 6.0 when using
RTPs. */
return -1;
+#elif defined (_WIN32)
+ /* Special case when oldfd and newfd are identical and are the standard
+ input, output or error as this makes Windows XP hangs. Note that we
+ do that only for standard file descriptors that are known to be valid. */
+ if (oldfd == newfd && newfd >= 0 && newfd <= 2)
+ return newfd;
+ else
+ return dup2 (oldfd, newfd);
#else
return dup2 (oldfd, newfd);
#endif
diff --git a/gcc/ada/aspects.adb b/gcc/ada/aspects.adb
index 9b707734b76..7cc218e1d98 100755
--- a/gcc/ada/aspects.adb
+++ b/gcc/ada/aspects.adb
@@ -180,6 +180,7 @@ package body Aspects is
N_Component_Declaration => True,
N_Entry_Declaration => True,
N_Exception_Declaration => True,
+ N_Exception_Renaming_Declaration => True,
N_Formal_Abstract_Subprogram_Declaration => True,
N_Formal_Concrete_Subprogram_Declaration => True,
N_Formal_Object_Declaration => True,
@@ -188,11 +189,14 @@ package body Aspects is
N_Full_Type_Declaration => True,
N_Function_Instantiation => True,
N_Generic_Package_Declaration => True,
+ N_Generic_Renaming_Declaration => True,
N_Generic_Subprogram_Declaration => True,
N_Object_Declaration => True,
+ N_Object_Renaming_Declaration => True,
N_Package_Declaration => True,
N_Package_Instantiation => True,
N_Package_Specification => True,
+ N_Package_Renaming_Declaration => True,
N_Private_Extension_Declaration => True,
N_Private_Type_Declaration => True,
N_Procedure_Instantiation => True,
@@ -202,6 +206,7 @@ package body Aspects is
N_Single_Task_Declaration => True,
N_Subprogram_Body => True,
N_Subprogram_Declaration => True,
+ N_Subprogram_Renaming_Declaration => True,
N_Subtype_Declaration => True,
N_Task_Body => True,
N_Task_Type_Declaration => True,
@@ -255,6 +260,7 @@ package body Aspects is
Aspect_Preelaborate_05 => Aspect_Preelaborate_05,
Aspect_Pure => Aspect_Pure,
Aspect_Pure_05 => Aspect_Pure_05,
+ Aspect_Pure_12 => Aspect_Pure_12,
Aspect_Remote_Call_Interface => Aspect_Remote_Call_Interface,
Aspect_Remote_Types => Aspect_Remote_Types,
Aspect_Shared_Passive => Aspect_Shared_Passive,
diff --git a/gcc/ada/aspects.ads b/gcc/ada/aspects.ads
index 582a71e7a55..c1dbe72cd3f 100755
--- a/gcc/ada/aspects.ads
+++ b/gcc/ada/aspects.ads
@@ -96,6 +96,7 @@ package Aspects is
Aspect_Preelaborate_05, -- GNAT
Aspect_Pure,
Aspect_Pure_05, -- GNAT
+ Aspect_Pure_12, -- GNAT
Aspect_Remote_Call_Interface,
Aspect_Remote_Types,
Aspect_Shared_Passive,
@@ -154,6 +155,7 @@ package Aspects is
Aspect_Compiler_Unit => True,
Aspect_Preelaborate_05 => True,
Aspect_Pure_05 => True,
+ Aspect_Pure_12 => True,
Aspect_Universal_Data => True,
Aspect_Ada_2005 => True,
Aspect_Ada_2012 => True,
@@ -324,6 +326,7 @@ package Aspects is
Aspect_Priority => Name_Priority,
Aspect_Pure => Name_Pure,
Aspect_Pure_05 => Name_Pure_05,
+ Aspect_Pure_12 => Name_Pure_12,
Aspect_Pure_Function => Name_Pure_Function,
Aspect_Read => Name_Read,
Aspect_Remote_Call_Interface => Name_Remote_Call_Interface,
diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb
index 67febfe1919..01f240fc034 100644
--- a/gcc/ada/checks.adb
+++ b/gcc/ada/checks.adb
@@ -442,7 +442,7 @@ package body Checks is
-- are cases (e.g. with pragma Debug) where generating the checks
-- can cause real trouble).
- if not Expander_Active then
+ if not Full_Expander_Active then
return;
end if;
@@ -878,7 +878,7 @@ package body Checks is
if Backend_Overflow_Checks_On_Target
or else not Do_Overflow_Check (N)
- or else not Expander_Active
+ or else not Full_Expander_Active
or else (Present (Parent (N))
and then Nkind (Parent (N)) = N_Type_Conversion
and then Integer_Promotion_Possible (Parent (N)))
@@ -1178,7 +1178,7 @@ package body Checks is
-- Nothing to do if discriminant checks are suppressed or else no code
-- is to be generated
- if not Expander_Active
+ if not Full_Expander_Active
or else Discriminant_Checks_Suppressed (T_Typ)
then
return;
@@ -1462,7 +1462,7 @@ package body Checks is
-- Don't actually use this value
begin
- if Expander_Active
+ if Full_Expander_Active
and then not Backend_Divide_Checks_On_Target
and then Check_Needed (Right, Division_Check)
then
@@ -2118,7 +2118,7 @@ package body Checks is
(not Length_Checks_Suppressed (Target_Typ));
begin
- if not Expander_Active then
+ if not Full_Expander_Active then
return;
end if;
@@ -2226,7 +2226,7 @@ package body Checks is
(not Range_Checks_Suppressed (Target_Typ));
begin
- if not Expander_Active or else not Checks_On then
+ if not Full_Expander_Active or else not Checks_On then
return;
end if;
@@ -5309,7 +5309,7 @@ package body Checks is
-- enhanced to check for an always True value in the condition and to
-- generate a compilation warning???
- if not Expander_Active or else not Checks_On then
+ if not Full_Expander_Active or else not Checks_On then
return;
end if;
@@ -5673,6 +5673,22 @@ package body Checks is
return;
end if;
+ -- No check needed for the Get_Current_Excep.all.all idiom generated by
+ -- the expander within exception handlers, since we know that the value
+ -- can never be null.
+
+ -- Is this really the right way to do this? Normally we generate such
+ -- code in the expander with checks off, and that's how we suppress this
+ -- kind of junk check ???
+
+ if Nkind (N) = N_Function_Call
+ and then Nkind (Name (N)) = N_Explicit_Dereference
+ and then Nkind (Prefix (Name (N))) = N_Identifier
+ and then Is_RTE (Entity (Prefix (Name (N))), RE_Get_Current_Excep)
+ then
+ return;
+ end if;
+
-- Otherwise install access check
Insert_Action (N,
@@ -6220,7 +6236,7 @@ package body Checks is
-- Start of processing for Selected_Length_Checks
begin
- if not Expander_Active then
+ if not Full_Expander_Active then
return Ret_Result;
end if;
@@ -6794,7 +6810,7 @@ package body Checks is
-- Start of processing for Selected_Range_Checks
begin
- if not Expander_Active then
+ if not Full_Expander_Active then
return Ret_Result;
end if;
diff --git a/gcc/ada/env.c b/gcc/ada/env.c
index 1719684034a..31c878e7795 100644
--- a/gcc/ada/env.c
+++ b/gcc/ada/env.c
@@ -110,8 +110,6 @@ __gnat_getenv (char *name, int *len, char **value)
#ifdef VMS
-static char *to_host_path_spec (char *);
-
typedef struct _ile3
{
unsigned short len, code;
diff --git a/gcc/ada/errout.adb b/gcc/ada/errout.adb
index 5993132cf81..c40179a5f7a 100644
--- a/gcc/ada/errout.adb
+++ b/gcc/ada/errout.adb
@@ -1286,30 +1286,37 @@ package body Errout is
Cur := First_Error_Msg;
while Cur /= No_Error_Msg loop
- if not Errors.Table (Cur).Deleted
- and then Warning_Specifically_Suppressed
- (Errors.Table (Cur).Sptr, Errors.Table (Cur).Text)
- then
- Delete_Warning (Cur);
+ declare
+ CE : Error_Msg_Object renames Errors.Table (Cur);
- -- If this is a continuation, delete previous messages
+ begin
+ if not CE.Deleted
+ and then
+ (Warning_Specifically_Suppressed (CE.Sptr, CE.Text)
+ or else
+ Warning_Specifically_Suppressed (CE.Optr, CE.Text))
+ then
+ Delete_Warning (Cur);
- F := Cur;
- while Errors.Table (F).Msg_Cont loop
- F := Errors.Table (F).Prev;
- Delete_Warning (F);
- end loop;
+ -- If this is a continuation, delete previous messages
- -- Delete any following continuations
+ F := Cur;
+ while Errors.Table (F).Msg_Cont loop
+ F := Errors.Table (F).Prev;
+ Delete_Warning (F);
+ end loop;
- F := Cur;
- loop
- F := Errors.Table (F).Next;
- exit when F = No_Error_Msg;
- exit when not Errors.Table (F).Msg_Cont;
- Delete_Warning (F);
- end loop;
- end if;
+ -- Delete any following continuations
+
+ F := Cur;
+ loop
+ F := Errors.Table (F).Next;
+ exit when F = No_Error_Msg;
+ exit when not Errors.Table (F).Msg_Cont;
+ Delete_Warning (F);
+ end loop;
+ end if;
+ end;
Cur := Errors.Table (Cur).Next;
end loop;
diff --git a/gcc/ada/errout.ads b/gcc/ada/errout.ads
index 5c1c92ce6b5..ea83a8a7b45 100644
--- a/gcc/ada/errout.ads
+++ b/gcc/ada/errout.ads
@@ -771,7 +771,8 @@ package Errout is
procedure Set_Specific_Warning_Off
(Loc : Source_Ptr;
Msg : String;
- Config : Boolean)
+ Config : Boolean;
+ Used : Boolean := False)
renames Erroutc.Set_Specific_Warning_Off;
-- This is called in response to the two argument form of pragma Warnings
-- where the first argument is OFF, and the second argument is the prefix
diff --git a/gcc/ada/erroutc.adb b/gcc/ada/erroutc.adb
index 649238018a1..f58a49a8a5a 100644
--- a/gcc/ada/erroutc.adb
+++ b/gcc/ada/erroutc.adb
@@ -1081,7 +1081,8 @@ package body Erroutc is
procedure Set_Specific_Warning_Off
(Loc : Source_Ptr;
Msg : String;
- Config : Boolean)
+ Config : Boolean;
+ Used : Boolean := False)
is
begin
Specific_Warnings.Append
@@ -1089,7 +1090,7 @@ package body Erroutc is
Msg => new String'(Msg),
Stop => Source_Last (Current_Source_File),
Open => True,
- Used => False,
+ Used => Used,
Config => Config));
end Set_Specific_Warning_Off;
@@ -1135,16 +1136,16 @@ package body Erroutc is
procedure Set_Warnings_Mode_Off (Loc : Source_Ptr) is
begin
- -- Don't bother with entries from instantiation copies, since we
- -- will already have a copy in the template, which is what matters
+ -- Don't bother with entries from instantiation copies, since we will
+ -- already have a copy in the template, which is what matters.
if Instantiation (Get_Source_File_Index (Loc)) /= No_Location then
return;
end if;
- -- If last entry in table already covers us, this is a redundant
- -- pragma Warnings (Off) and can be ignored. This also handles the
- -- case where all warnings are suppressed by command line switch.
+ -- If last entry in table already covers us, this is a redundant pragma
+ -- Warnings (Off) and can be ignored. This also handles the case where
+ -- all warnings are suppressed by command line switch.
if Warnings.Last >= Warnings.First
and then Warnings.Table (Warnings.Last).Start <= Loc
@@ -1152,9 +1153,9 @@ package body Erroutc is
then
return;
- -- Otherwise establish a new entry, extending from the location of
- -- the pragma to the end of the current source file. This ending
- -- point will be adjusted by a subsequent pragma Warnings (On).
+ -- Otherwise establish a new entry, extending from the location of the
+ -- pragma to the end of the current source file. This ending point will
+ -- be adjusted by a subsequent pragma Warnings (On).
else
Warnings.Increment_Last;
@@ -1170,8 +1171,8 @@ package body Erroutc is
procedure Set_Warnings_Mode_On (Loc : Source_Ptr) is
begin
- -- Don't bother with entries from instantiation copies, since we
- -- will already have a copy in the template, which is what matters
+ -- Don't bother with entries from instantiation copies, since we will
+ -- already have a copy in the template, which is what matters.
if Instantiation (Get_Source_File_Index (Loc)) /= No_Location then
return;
diff --git a/gcc/ada/erroutc.ads b/gcc/ada/erroutc.ads
index a2ac46329d4..6c077b0f2e3 100644
--- a/gcc/ada/erroutc.ads
+++ b/gcc/ada/erroutc.ads
@@ -445,7 +445,8 @@ package Erroutc is
procedure Set_Specific_Warning_Off
(Loc : Source_Ptr;
Msg : String;
- Config : Boolean);
+ Config : Boolean;
+ Used : Boolean := False);
-- This is called in response to the two argument form of pragma Warnings
-- where the first argument is OFF, and the second argument is a string
-- which identifies a specific warning to be suppressed. The first argument
@@ -453,6 +454,8 @@ package Erroutc is
-- string from the pragma. Loc is the location of the pragma (which is the
-- start of the range to suppress). Config is True for the configuration
-- pragma case (where there is no requirement for a matching OFF pragma).
+ -- Used is set True to disable the check that the warning actually has
+ -- has the effect of suppressing a warning.
procedure Set_Specific_Warning_On
(Loc : Source_Ptr;
diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb
index 57e94d29840..ac6fdf9f26e 100644
--- a/gcc/ada/exp_attr.adb
+++ b/gcc/ada/exp_attr.adb
@@ -2117,21 +2117,38 @@ package body Exp_Attr is
-- computation to be completed in the back-end, since we don't know what
-- layout will be chosen.
- when Attribute_First_Bit => First_Bit : declare
+ when Attribute_First_Bit => First_Bit_Attr : declare
CE : constant Entity_Id := Entity (Selector_Name (Pref));
begin
- if Known_Static_Component_Bit_Offset (CE) then
+ -- In Ada 2005 (or later) if we have the standard nondefault
+ -- bit order, then we return the original value as given in
+ -- the component clause (RM 2005 13.5.2(3/2)).
+
+ if Present (Component_Clause (CE))
+ and then Ada_Version >= Ada_2005
+ and then not Reverse_Bit_Order (Scope (CE))
+ then
Rewrite (N,
Make_Integer_Literal (Loc,
- Component_Bit_Offset (CE) mod System_Storage_Unit));
+ Intval => Expr_Value (First_Bit (Component_Clause (CE)))));
+ Analyze_And_Resolve (N, Typ);
+
+ -- Otherwise (Ada 83/95 or Ada 2005 or later with reverse bit order),
+ -- rewrite with normalized value if we know it statically.
+ elsif Known_Static_Component_Bit_Offset (CE) then
+ Rewrite (N,
+ Make_Integer_Literal (Loc,
+ Component_Bit_Offset (CE) mod System_Storage_Unit));
Analyze_And_Resolve (N, Typ);
+ -- Otherwise left to back end, just do universal integer checks
+
else
Apply_Universal_Integer_Attribute_Checks (N);
end if;
- end First_Bit;
+ end First_Bit_Attr;
-----------------
-- Fixed_Value --
@@ -2680,24 +2697,41 @@ package body Exp_Attr is
-- the computation up to the back end, since we don't know what layout
-- will be chosen.
- when Attribute_Last_Bit => Last_Bit : declare
+ when Attribute_Last_Bit => Last_Bit_Attr : declare
CE : constant Entity_Id := Entity (Selector_Name (Pref));
begin
- if Known_Static_Component_Bit_Offset (CE)
+ -- In Ada 2005 (or later) if we have the standard nondefault
+ -- bit order, then we return the original value as given in
+ -- the component clause (RM 2005 13.5.2(4/2)).
+
+ if Present (Component_Clause (CE))
+ and then Ada_Version >= Ada_2005
+ and then not Reverse_Bit_Order (Scope (CE))
+ then
+ Rewrite (N,
+ Make_Integer_Literal (Loc,
+ Intval => Expr_Value (Last_Bit (Component_Clause (CE)))));
+ Analyze_And_Resolve (N, Typ);
+
+ -- Otherwise (Ada 83/95 or Ada 2005 or later with reverse bit order),
+ -- rewrite with normalized value if we know it statically.
+
+ elsif Known_Static_Component_Bit_Offset (CE)
and then Known_Static_Esize (CE)
then
Rewrite (N,
Make_Integer_Literal (Loc,
Intval => (Component_Bit_Offset (CE) mod System_Storage_Unit)
+ Esize (CE) - 1));
-
Analyze_And_Resolve (N, Typ);
+ -- Otherwise leave to back end, just apply universal integer checks
+
else
Apply_Universal_Integer_Attribute_Checks (N);
end if;
- end Last_Bit;
+ end Last_Bit_Attr;
------------------
-- Leading_Part --
@@ -2955,6 +2989,52 @@ package body Exp_Attr is
Analyze_And_Resolve (N, Typ);
end Mantissa;
+ ----------------------------------
+ -- Max_Size_In_Storage_Elements --
+ ----------------------------------
+
+ when Attribute_Max_Size_In_Storage_Elements =>
+ Apply_Universal_Integer_Attribute_Checks (N);
+
+ -- Heap-allocated controlled objects contain two extra pointers which
+ -- are not part of the actual type. Transform the attribute reference
+ -- into a runtime expression to add the size of the hidden header.
+
+ -- Do not perform this expansion on .NET/JVM targets because the
+ -- two pointers are already present in the type.
+
+ if VM_Target = No_VM
+ and then Nkind (N) = N_Attribute_Reference
+ and then Needs_Finalization (Ptyp)
+ and then not Header_Size_Added (N)
+ then
+ Set_Header_Size_Added (N);
+
+ -- Generate:
+ -- P'Max_Size_In_Storage_Elements +
+ -- Universal_Integer
+ -- (Header_Size_With_Padding (Ptyp'Alignment))
+
+ Rewrite (N,
+ Make_Op_Add (Loc,
+ Left_Opnd => Relocate_Node (N),
+ Right_Opnd =>
+ Convert_To (Universal_Integer,
+ Make_Function_Call (Loc,
+ Name =>
+ New_Reference_To
+ (RTE (RE_Header_Size_With_Padding), Loc),
+
+ Parameter_Associations => New_List (
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ New_Reference_To (Ptyp, Loc),
+ Attribute_Name => Name_Alignment))))));
+
+ Analyze (N);
+ return;
+ end if;
+
--------------------
-- Mechanism_Code --
--------------------
@@ -3495,21 +3575,41 @@ package body Exp_Attr is
-- the computation up to the back end, since we don't know what layout
-- will be chosen.
- when Attribute_Position => Position :
+ when Attribute_Position => Position_Attr :
declare
CE : constant Entity_Id := Entity (Selector_Name (Pref));
begin
if Present (Component_Clause (CE)) then
- Rewrite (N,
- Make_Integer_Literal (Loc,
- Intval => Component_Bit_Offset (CE) / System_Storage_Unit));
+
+ -- In Ada 2005 (or later) if we have the standard nondefault
+ -- bit order, then we return the original value as given in
+ -- the component clause (RM 2005 13.5.2(2/2)).
+
+ if Ada_Version >= Ada_2005
+ and then not Reverse_Bit_Order (Scope (CE))
+ then
+ Rewrite (N,
+ Make_Integer_Literal (Loc,
+ Intval => Expr_Value (Position (Component_Clause (CE)))));
+
+ -- Otherwise (Ada 83 or 95, or reverse bit order specified in
+ -- later Ada version), return the normalized value.
+
+ else
+ Rewrite (N,
+ Make_Integer_Literal (Loc,
+ Intval => Component_Bit_Offset (CE) / System_Storage_Unit));
+ end if;
+
Analyze_And_Resolve (N, Typ);
+ -- If back end is doing things, just apply universal integer checks
+
else
Apply_Universal_Integer_Attribute_Checks (N);
end if;
- end Position;
+ end Position_Attr;
----------
-- Pred --
@@ -5518,8 +5618,7 @@ package body Exp_Attr is
-- that the result is in range.
when Attribute_Aft |
- Attribute_Max_Alignment_For_Allocation |
- Attribute_Max_Size_In_Storage_Elements =>
+ Attribute_Max_Alignment_For_Allocation =>
Apply_Universal_Integer_Attribute_Checks (N);
-- The following attributes should not appear at this stage, since they
diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb
index fd75b158449..d7f30991fca 100644
--- a/gcc/ada/exp_ch5.adb
+++ b/gcc/ada/exp_ch5.adb
@@ -3178,11 +3178,13 @@ package body Exp_Ch5 is
-- Determine the advancement and initialization steps for the
-- cursor.
- -- Must verify that the container has a reverse iterator ???
+ -- Analysis of the expanded loop will verify that the container
+ -- has a reverse iterator.
if Reverse_Present (I_Spec) then
Name_Init := Name_Last;
Name_Step := Name_Previous;
+
else
Name_Init := Name_First;
Name_Step := Name_Next;
@@ -3231,7 +3233,7 @@ package body Exp_Ch5 is
Make_Selected_Component (Loc,
Prefix => New_Occurrence_Of (Pack, Loc),
Selector_Name =>
- Make_Identifier (Loc, Name_Has_Element)),
+ Make_Identifier (Loc, Name_Has_Element)),
Parameter_Associations =>
New_List (
@@ -3248,20 +3250,19 @@ package body Exp_Ch5 is
-- I : Iterator_Type renames Container;
-- C : Pack.Cursor_Type := Container.[First | Last];
- declare
- Decl1 : Node_Id;
- Decl2 : Node_Id;
+ Insert_Action (N,
+ Make_Object_Renaming_Declaration (Loc,
+ Defining_Identifier => Iterator,
+ Subtype_Mark => New_Occurrence_Of (Iter_Type, Loc),
+ Name => Relocate_Node (Name (I_Spec))));
- begin
- Decl1 :=
- Make_Object_Renaming_Declaration (Loc,
- Defining_Identifier => Iterator,
- Subtype_Mark => New_Occurrence_Of (Iter_Type, Loc),
- Name => Relocate_Node (Name (I_Spec)));
+ -- Create declaration for cursor
- -- Create declaration for cursor
+ declare
+ Decl : Node_Id;
- Decl2 :=
+ begin
+ Decl :=
Make_Object_Declaration (Loc,
Defining_Identifier => Cursor,
Object_Definition =>
@@ -3272,18 +3273,15 @@ package body Exp_Ch5 is
Selector_Name =>
Make_Identifier (Loc, Name_Init)));
- Set_Assignment_OK (Decl2);
-
- Insert_Actions (N, New_List (Decl1, Decl2));
- end;
+ -- The cursor is only modified in expanded code, so it appears
+ -- as unassigned to the warning machinery. We must suppress
+ -- this spurious warning explicitly.
- -- The Iterator is not modified in the source, but of course will
- -- be updated in the generated code. Indicate that it is actually
- -- set to prevent spurious warnings. Ditto for the Cursor, which
- -- is modified indirectly in generated code.
+ Set_Warnings_Off (Cursor);
+ Set_Assignment_OK (Decl);
- Set_Never_Set_In_Source (Iterator, False);
- Set_Never_Set_In_Source (Cursor, False);
+ Insert_Action (N, Decl);
+ end;
-- If the range of iteration is given by a function call that
-- returns a container, the finalization actions have been saved
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index 6049c452cb8..4c9460438d3 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -1750,24 +1750,50 @@ package body Exp_Ch6 is
if not Is_Empty_List (Post_Call) then
- -- If call is not a list member, it must be the triggering statement
- -- of a triggering alternative or an entry call alternative, and we
- -- can add the post call stuff to the corresponding statement list.
+ -- Cases where the call is not a member of a statement list
if not Is_List_Member (N) then
declare
- P : constant Node_Id := Parent (N);
+ P : Node_Id := Parent (N);
begin
- pragma Assert (Nkind_In (P, N_Triggering_Alternative,
- N_Entry_Call_Alternative));
+ -- In Ada 2012 the call may be a function call in an expression
+ -- (since OUT and IN OUT parameters are now allowed for such
+ -- calls. The write-back of (in)-out parameters is handled
+ -- by the back-end, but the constraint checks generated when
+ -- subtypes of formal and actual don't match must be inserted
+ -- in the form of assignments, at the nearest point after the
+ -- declaration or statement that contains the call.
+
+ if Ada_Version >= Ada_2012
+ and then Nkind (N) = N_Function_Call
+ then
+ while Nkind (P) not in N_Declaration
+ and then
+ Nkind (P) not in N_Statement_Other_Than_Procedure_Call
+ loop
+ P := Parent (P);
+ end loop;
+
+ Insert_Actions_After (P, Post_Call);
+
+ -- If not the special Ada 2012 case of a function call, then
+ -- we must have the triggering statement of a triggering
+ -- alternative or an entry call alternative, and we can add
+ -- the post call stuff to the corresponding statement list.
- if Is_Non_Empty_List (Statements (P)) then
- Insert_List_Before_And_Analyze
- (First (Statements (P)), Post_Call);
else
- Set_Statements (P, Post_Call);
+ pragma Assert (Nkind_In (P, N_Triggering_Alternative,
+ N_Entry_Call_Alternative));
+
+ if Is_Non_Empty_List (Statements (P)) then
+ Insert_List_Before_And_Analyze
+ (First (Statements (P)), Post_Call);
+ else
+ Set_Statements (P, Post_Call);
+ end if;
end if;
+
end;
-- Otherwise, normal case where N is in a statement sequence,
@@ -2764,7 +2790,7 @@ package body Exp_Ch6 is
Next_Formal (Formal);
end loop;
- -- If we are calling an Ada2012 function which needs to have the
+ -- If we are calling an Ada 2012 function which needs to have the
-- "accessibility level determined by the point of call" (AI05-0234)
-- passed in to it, then pass it in.
@@ -6674,6 +6700,14 @@ package body Exp_Ch6 is
Make_Explicit_Dereference (Loc,
Prefix => New_Reference_To (Temp, Loc)));
+ -- Ada 2005 (AI-251): If the type of the returned object is
+ -- an interface then add an implicit type conversion to force
+ -- displacement of the "this" pointer.
+
+ if Is_Interface (R_Type) then
+ Rewrite (Exp, Convert_To (R_Type, Relocate_Node (Exp)));
+ end if;
+
Analyze_And_Resolve (Exp, R_Type);
end;
@@ -7779,6 +7813,15 @@ package body Exp_Ch6 is
-- to the object created by the allocator).
Rewrite (Allocator, Make_Reference (Loc, Relocate_Node (Function_Call)));
+
+ -- Ada 2005 (AI-251): If the type of the allocator is an interface then
+ -- generate an implicit conversion to force displacement of the "this"
+ -- pointer.
+
+ if Is_Interface (Designated_Type (Acc_Type)) then
+ Rewrite (Allocator, Convert_To (Acc_Type, Relocate_Node (Allocator)));
+ end if;
+
Analyze_And_Resolve (Allocator, Acc_Type);
end Make_Build_In_Place_Call_In_Allocator;
@@ -7954,6 +7997,7 @@ package body Exp_Ch6 is
Obj_Id : Entity_Id;
Ptr_Typ : Entity_Id;
Ptr_Typ_Decl : Node_Id;
+ New_Expr : Node_Id;
Result_Subt : Entity_Id;
Target : Node_Id;
@@ -8033,16 +8077,20 @@ package body Exp_Ch6 is
Insert_After_And_Analyze (Assign, Ptr_Typ_Decl);
-- Finally, create an access object initialized to a reference to the
- -- function call.
+ -- function call. We know this access value is non-null, so mark the
+ -- entity accordingly to suppress junk access checks.
+
+ New_Expr := Make_Reference (Loc, Relocate_Node (Func_Call));
- Obj_Id := Make_Temporary (Loc, 'R');
+ Obj_Id := Make_Temporary (Loc, 'R', New_Expr);
Set_Etype (Obj_Id, Ptr_Typ);
+ Set_Is_Known_Non_Null (Obj_Id);
Obj_Decl :=
Make_Object_Declaration (Loc,
Defining_Identifier => Obj_Id,
Object_Definition => New_Reference_To (Ptr_Typ, Loc),
- Expression => Make_Reference (Loc, Relocate_Node (Func_Call)));
+ Expression => New_Expr);
Insert_After_And_Analyze (Ptr_Typ_Decl, Obj_Decl);
Rewrite (Assign, Make_Null_Statement (Loc));
@@ -8295,12 +8343,14 @@ package body Exp_Ch6 is
end if;
-- Finally, create an access object initialized to a reference to the
- -- function call.
+ -- function call. We know this access value cannot be null, so mark the
+ -- entity accordingly to suppress the access check.
New_Expr := Make_Reference (Loc, Relocate_Node (Func_Call));
Def_Id := Make_Temporary (Loc, 'R', New_Expr);
Set_Etype (Def_Id, Ref_Type);
+ Set_Is_Known_Non_Null (Def_Id);
Insert_After_And_Analyze (Ptr_Typ_Decl,
Make_Object_Declaration (Loc,
@@ -8499,8 +8549,8 @@ package body Exp_Ch6 is
return False;
-- Handle a corner case, a cross-dialect subp renaming. For example,
- -- an Ada2012 renaming of an Ada05 subprogram. This can occur when a
- -- non-Ada2012 unit references predefined runtime units.
+ -- an Ada 2012 renaming of an Ada 2005 subprogram. This can occur when
+ -- an Ada 2005 (or earlier) unit references predefined run-time units.
elsif Present (Alias (Func_Id)) then
diff --git a/gcc/ada/exp_imgv.adb b/gcc/ada/exp_imgv.adb
index 78d9b006abc..c8529ce2a51 100644
--- a/gcc/ada/exp_imgv.adb
+++ b/gcc/ada/exp_imgv.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2001-2010, Free Software Foundation, Inc. --
+-- Copyright (C) 2001-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- --
@@ -245,7 +245,10 @@ package body Exp_Imgv is
-- Snn (1 .. Pnn) then occurs as in the other cases. A special case is
-- when pragma Discard_Names applies, in which case we replace expr by:
- -- Missing ???
+ -- (rt'Pos (expr))'Img
+
+ -- So that the result is a space followed by the decimal value for the
+ -- position of the enumeration value in the enumeration type.
procedure Expand_Image_Attribute (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N);
@@ -368,7 +371,7 @@ package body Exp_Imgv is
or else No (Lit_Strings (Root_Type (Ptyp)))
then
-- When pragma Discard_Names applies to the first subtype, build
- -- (Pref'Pos)'Img.
+ -- (Pref'Pos (Expr))'Img.
Rewrite (N,
Make_Attribute_Reference (Loc,
@@ -1055,9 +1058,14 @@ package body Exp_Imgv is
-- typ'Pos (Typ'Last))
-- Wide_Character_Encoding_Method);
- -- where typS and typI are the enumeration image strings and
- -- indexes table, as described in Build_Enumeration_Image_Tables.
- -- NN is 8/16/32 for depending on the element type for typI.
+ -- where typS and typI are the enumeration image strings and indexes
+ -- table, as described in Build_Enumeration_Image_Tables. NN is 8/16/32
+ -- for depending on the element type for typI.
+
+ -- Finally if Discard_Names is in effect for an enumeration type, then
+ -- a special conditional expression is built that yields the space needed
+ -- for the decimal representation of the largest pos value in the subtype.
+ -- See code below for details.
procedure Expand_Width_Attribute (N : Node_Id; Attr : Atype := Normal) is
Loc : constant Source_Ptr := Sloc (N);
@@ -1065,10 +1073,10 @@ package body Exp_Imgv is
Pref : constant Node_Id := Prefix (N);
Ptyp : constant Entity_Id := Etype (Pref);
Rtyp : constant Entity_Id := Root_Type (Ptyp);
- XX : RE_Id;
- YY : Entity_Id;
Arglist : List_Id;
Ttyp : Entity_Id;
+ XX : RE_Id;
+ YY : Entity_Id;
begin
-- Types derived from Standard.Boolean
@@ -1125,7 +1133,6 @@ package body Exp_Imgv is
-- Real types
elsif Is_Real_Type (Rtyp) then
-
Rewrite (N,
Make_Conditional_Expression (Loc,
Expressions => New_List (
@@ -1155,21 +1162,113 @@ package body Exp_Imgv is
else
pragma Assert (Is_Enumeration_Type (Rtyp));
- if Discard_Names (Rtyp) then
+ -- Whenever pragma Discard_Names is in effect, the value we need
+ -- is the value needed to accomodate the largest integer pos value
+ -- in the range of the subtype + 1 for the space at the start. We
+ -- build:
- -- This is a configurable run-time, or else a restriction is in
- -- effect. In either case the attribute cannot be supported. Force
- -- a load error from Rtsfind to generate an appropriate message,
- -- as is done with other ZFP violations.
+ -- Tnn : constant Integer := Rtyp'Pos (Ptyp'Last)
+ -- and replace the expression by
+
+ -- (if Ptyp'Range_Length = 0 then 0
+ -- else (if Tnn < 10 then 2
+ -- else (if Tnn < 100 then 3
+ -- ...
+ -- else n)))...
+
+ -- where n is equal to Rtyp'Pos (Rtyp'Last) + 1
+
+ -- Note: The above processing is in accordance with the intent of
+ -- the RM, which is that Width should be related to the impl-defined
+ -- behavior of Image. It is not clear what this means if Image is
+ -- not defined (as in the configurable run-time case for GNAT) and
+ -- gives an error at compile time.
+
+ -- We choose in this case to just go ahead and implement Width the
+ -- same way, returning what Image would have returned if it has been
+ -- available in the configurable run-time library.
+
+ if Discard_Names (Rtyp) then
declare
- Discard : constant Entity_Id := RTE (RE_Null);
- pragma Unreferenced (Discard);
+ Tnn : constant Entity_Id := Make_Temporary (Loc, 'T');
+ Cexpr : Node_Id;
+ P : Int;
+ M : Int;
+ K : Int;
+
begin
+ Insert_Action (N,
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Tnn,
+ Constant_Present => True,
+ Object_Definition =>
+ New_Occurrence_Of (Standard_Integer, Loc),
+ Expression =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Rtyp, Loc),
+ Attribute_Name => Name_Pos,
+ Expressions => New_List (
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Ptyp, Loc),
+ Attribute_Name => Name_Last)))));
+
+ -- OK, now we need to build the conditional expression. First
+ -- get the value of M, the largest possible value needed.
+
+ P := UI_To_Int
+ (Enumeration_Pos (Entity (Type_High_Bound (Rtyp))));
+
+ K := 1;
+ M := 1;
+ while M < P loop
+ M := M * 10;
+ K := K + 1;
+ end loop;
+
+ -- Build inner else
+
+ Cexpr := Make_Integer_Literal (Loc, K);
+
+ -- Wrap in inner if's until counted down to 2
+
+ while K > 2 loop
+ M := M / 10;
+ K := K - 1;
+
+ Cexpr :=
+ Make_Conditional_Expression (Loc,
+ Expressions => New_List (
+ Make_Op_Lt (Loc,
+ Left_Opnd => New_Occurrence_Of (Tnn, Loc),
+ Right_Opnd => Make_Integer_Literal (Loc, M)),
+ Make_Integer_Literal (Loc, K),
+ Cexpr));
+ end loop;
+
+ -- Add initial comparison for null range and we are done, so
+ -- rewrite the attribute occurrence with this expression.
+
+ Rewrite (N,
+ Convert_To (Typ,
+ Make_Conditional_Expression (Loc,
+ Expressions => New_List (
+ Make_Op_Eq (Loc,
+ Left_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Ptyp, Loc),
+ Attribute_Name => Name_Range_Length),
+ Right_Opnd => Make_Integer_Literal (Loc, 0)),
+ Make_Integer_Literal (Loc, 0),
+ Cexpr))));
+
+ Analyze_And_Resolve (N, Typ);
return;
end;
end if;
+ -- Normal case, not Discard_Names
+
Ttyp := Component_Type (Etype (Lit_Indexes (Rtyp)));
case Attr is
diff --git a/gcc/ada/exp_intr.adb b/gcc/ada/exp_intr.adb
index ce7c0dcc979..b116a8a28f0 100644
--- a/gcc/ada/exp_intr.adb
+++ b/gcc/ada/exp_intr.adb
@@ -1123,6 +1123,10 @@ package body Exp_Intr is
D_Type : Entity_Id;
begin
+ -- Perform minor decoration as it is needed by the side effect
+ -- removal mechanism.
+
+ Set_Etype (Deref, Desig_T);
Set_Parent (Deref, Free_Node);
D_Subtyp := Make_Subtype_From_Expr (Deref, Desig_T);
diff --git a/gcc/ada/exp_prag.adb b/gcc/ada/exp_prag.adb
index 22e9bb04691..8cb084d6ba2 100644
--- a/gcc/ada/exp_prag.adb
+++ b/gcc/ada/exp_prag.adb
@@ -270,10 +270,17 @@ package body Exp_Prag is
procedure Expand_Pragma_Check (N : Node_Id) is
Cond : constant Node_Id := Arg2 (N);
- Loc : constant Source_Ptr := Sloc (Cond);
Nam : constant Name_Id := Chars (Arg1 (N));
Msg : Node_Id;
+ Loc : constant Source_Ptr := Sloc (First_Node (Cond));
+ -- Source location used in the case of a failed assertion. Note that
+ -- the source location of the expression is not usually the best choice
+ -- here. For example, it gets located on the last AND keyword in a
+ -- chain of boolean expressiond AND'ed together. It is best to put the
+ -- message on the first character of the assertion, which is the effect
+ -- of the First_Node call here.
+
begin
-- We already know that this check is enabled, because otherwise the
-- semantic pass dealt with rewriting the assertion (see Sem_Prag)
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index e675da82889..c67d0117897 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -6424,13 +6424,14 @@ package body Exp_Util is
if not Expander_Active then
return;
+ end if;
-- Cannot generate temporaries if the invocation to remove side effects
-- was issued too early and the type of the expression is not resolved
-- (this happens because routines Duplicate_Subexpr_XX implicitly invoke
-- Remove_Side_Effects).
- elsif No (Exp_Type)
+ if No (Exp_Type)
or else Ekind (Exp_Type) = E_Access_Attribute_Type
then
return;
@@ -6710,8 +6711,13 @@ package body Exp_Util is
if Alfa_Mode then
New_Exp := E;
+
+ -- Otherwise generate reference, marking the value as non-null
+ -- since we know it cannot be null and we don't want a check.
+
else
New_Exp := Make_Reference (Loc, E);
+ Set_Is_Known_Non_Null (Def_Id);
end if;
end if;
diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb
index b1a33d58da1..16521f9f6d7 100644
--- a/gcc/ada/freeze.adb
+++ b/gcc/ada/freeze.adb
@@ -1342,7 +1342,9 @@ package body Freeze is
-- If an incomplete type is still not frozen, this may be a
-- premature freezing because of a body declaration that follows.
- -- Indicate where the freezing took place.
+ -- Indicate where the freezing took place. Freezing will happen
+ -- if the body comes from source, but not if it is internally
+ -- generated, for example as the body of a type invariant.
-- If the freezing is caused by the end of the current declarative
-- part, it is a Taft Amendment type, and there is no error.
@@ -1360,8 +1362,9 @@ package body Freeze is
N_Protected_Body,
N_Task_Body)
or else Nkind (Bod) in N_Body_Stub)
- and then
- List_Containing (After) = List_Containing (Parent (E))
+ and then
+ List_Containing (After) = List_Containing (Parent (E))
+ and then Comes_From_Source (Bod)
then
Error_Msg_Sloc := Sloc (Next (After));
Error_Msg_NE
@@ -4239,7 +4242,8 @@ package body Freeze is
-- By default, if no size clause is present, an enumeration type with
-- Convention C is assumed to interface to a C enum, and has integer
-- size. This applies to types. For subtypes, verify that its base
- -- type has no size clause either.
+ -- type has no size clause either. Treat other foreign conventions
+ -- in the same way, and also make sure alignment is set right.
if Has_Foreign_Convention (Typ)
and then not Has_Size_Clause (Typ)
@@ -4247,6 +4251,7 @@ package body Freeze is
and then Esize (Typ) < Standard_Integer_Size
then
Init_Esize (Typ, Standard_Integer_Size);
+ Set_Alignment (Typ, Alignment (Standard_Integer));
else
-- If the enumeration type interfaces to C, and it has a size clause
diff --git a/gcc/ada/frontend.adb b/gcc/ada/frontend.adb
index 2dad57a3b3b..35e7d9e769b 100644
--- a/gcc/ada/frontend.adb
+++ b/gcc/ada/frontend.adb
@@ -226,6 +226,12 @@ begin
Opt.Suppress_Options := Scope_Suppress;
end;
+ -- This is where we can capture the value of the compilation unit specific
+ -- restrictions that have been set by the config pragma files (or from
+ -- Targparm), for later restoration when processing e.g. subunits.
+
+ Save_Config_Cunit_Boolean_Restrictions;
+
-- If there was a -gnatem switch, initialize the mappings of unit names to
-- file names and of file names to path names from the mapping file.
diff --git a/gcc/ada/g-exptty.adb b/gcc/ada/g-exptty.adb
new file mode 100644
index 00000000000..7ec04727d07
--- /dev/null
+++ b/gcc/ada/g-exptty.adb
@@ -0,0 +1,309 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT LIBRARY COMPONENTS --
+-- --
+-- G N A T . E X P E C T . T T Y --
+-- --
+-- S p e c --
+-- --
+-- 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 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. --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+with GNAT.OS_Lib; use GNAT.OS_Lib;
+
+with System; use System;
+
+package body GNAT.Expect.TTY is
+
+ On_Windows : constant Boolean := Directory_Separator = '\';
+ -- True when on Windows
+
+ -----------
+ -- Close --
+ -----------
+
+ overriding procedure Close
+ (Descriptor : in out TTY_Process_Descriptor;
+ Status : out Integer)
+ is
+ procedure Terminate_Process (Process : System.Address);
+ pragma Import (C, Terminate_Process, "__gnat_terminate_process");
+
+ function Waitpid (Process : System.Address) return Integer;
+ pragma Import (C, Waitpid, "__gnat_waitpid");
+ -- Wait for a specific process id, and return its exit code
+
+ procedure Free_Process (Process : System.Address);
+ pragma Import (C, Free_Process, "__gnat_free_process");
+
+ procedure Close_TTY (Process : System.Address);
+ pragma Import (C, Close_TTY, "__gnat_close_tty");
+
+ begin
+ -- If we haven't already closed the process
+
+ if Descriptor.Process = System.Null_Address then
+ Status := -1;
+
+ else
+ if Descriptor.Input_Fd /= Invalid_FD then
+ Close (Descriptor.Input_Fd);
+ end if;
+
+ if Descriptor.Error_Fd /= Descriptor.Output_Fd
+ and then Descriptor.Error_Fd /= Invalid_FD
+ then
+ Close (Descriptor.Error_Fd);
+ end if;
+
+ if Descriptor.Output_Fd /= Invalid_FD then
+ Close (Descriptor.Output_Fd);
+ end if;
+
+ -- Send a Ctrl-C to the process first. This way, if the
+ -- launched process is a "sh" or "cmd", the child processes
+ -- will get terminated as well. Otherwise, terminating the
+ -- main process brutally will leave the children running.
+
+ Interrupt (Descriptor);
+ delay 0.05;
+
+ Terminate_Process (Descriptor.Process);
+ Status := Waitpid (Descriptor.Process);
+
+ if not On_Windows then
+ Close_TTY (Descriptor.Process);
+ end if;
+
+ Free_Process (Descriptor.Process'Address);
+ Descriptor.Process := System.Null_Address;
+
+ GNAT.OS_Lib.Free (Descriptor.Buffer);
+ Descriptor.Buffer_Size := 0;
+ end if;
+ end Close;
+
+ overriding procedure Close (Descriptor : in out TTY_Process_Descriptor) is
+ Status : Integer;
+ begin
+ Close (Descriptor, Status);
+ end Close;
+
+ -----------------------------
+ -- Close_Pseudo_Descriptor --
+ -----------------------------
+
+ procedure Close_Pseudo_Descriptor
+ (Descriptor : in out TTY_Process_Descriptor)
+ is
+ begin
+ Descriptor.Buffer_Size := 0;
+ GNAT.OS_Lib.Free (Descriptor.Buffer);
+ end Close_Pseudo_Descriptor;
+
+ ---------------
+ -- Interrupt --
+ ---------------
+
+ overriding procedure Interrupt
+ (Descriptor : in out TTY_Process_Descriptor)
+ is
+ procedure Internal (Process : System.Address);
+ pragma Import (C, Internal, "__gnat_interrupt_process");
+ begin
+ if Descriptor.Process /= System.Null_Address then
+ Internal (Descriptor.Process);
+ end if;
+ end Interrupt;
+
+ procedure Interrupt (Pid : Integer) is
+ procedure Internal (Pid : Integer);
+ pragma Import (C, Internal, "__gnat_interrupt_pid");
+ begin
+ Internal (Pid);
+ end Interrupt;
+
+ -----------------------
+ -- Pseudo_Descriptor --
+ -----------------------
+
+ procedure Pseudo_Descriptor
+ (Descriptor : out TTY_Process_Descriptor'Class;
+ TTY : GNAT.TTY.TTY_Handle;
+ Buffer_Size : Natural := 4096) is
+ begin
+ Descriptor.Input_Fd := GNAT.TTY.TTY_Descriptor (TTY);
+ Descriptor.Output_Fd := Descriptor.Input_Fd;
+
+ -- Create the buffer
+
+ Descriptor.Buffer_Size := Buffer_Size;
+
+ if Buffer_Size /= 0 then
+ Descriptor.Buffer := new String (1 .. Positive (Buffer_Size));
+ end if;
+ end Pseudo_Descriptor;
+
+ ----------
+ -- Send --
+ ----------
+
+ overriding procedure Send
+ (Descriptor : in out TTY_Process_Descriptor;
+ Str : String;
+ Add_LF : Boolean := True;
+ Empty_Buffer : Boolean := False)
+ is
+ Header : String (1 .. 5);
+ Length : Natural;
+ Ret : Natural;
+
+ procedure Internal
+ (Process : System.Address;
+ S : in out String;
+ Length : Natural;
+ Ret : out Natural);
+ pragma Import (C, Internal, "__gnat_send_header");
+
+ begin
+ Length := Str'Length;
+
+ if Add_LF then
+ Length := Length + 1;
+ end if;
+
+ Internal (Descriptor.Process, Header, Length, Ret);
+
+ if Ret = 1 then
+
+ -- Need to use the header
+
+ GNAT.Expect.Send
+ (Process_Descriptor (Descriptor),
+ Header & Str, Add_LF, Empty_Buffer);
+
+ else
+ GNAT.Expect.Send
+ (Process_Descriptor (Descriptor),
+ Str, Add_LF, Empty_Buffer);
+ end if;
+ end Send;
+
+ --------------
+ -- Set_Size --
+ --------------
+
+ procedure Set_Size
+ (Descriptor : in out TTY_Process_Descriptor'Class;
+ Rows : Natural;
+ Columns : Natural)
+ is
+ procedure Internal (Process : System.Address; R, C : Integer);
+ pragma Import (C, Internal, "__gnat_setup_winsize");
+ begin
+ if Descriptor.Process /= System.Null_Address then
+ Internal (Descriptor.Process, Rows, Columns);
+ end if;
+ end Set_Size;
+
+ ---------------------------
+ -- Set_Up_Communications --
+ ---------------------------
+
+ overriding procedure Set_Up_Communications
+ (Pid : in out TTY_Process_Descriptor;
+ Err_To_Out : Boolean;
+ Pipe1 : access Pipe_Type;
+ Pipe2 : access Pipe_Type;
+ Pipe3 : access Pipe_Type)
+ is
+ pragma Unreferenced (Err_To_Out, Pipe1, Pipe2, Pipe3);
+
+ function Internal (Process : System.Address) return Integer;
+ pragma Import (C, Internal, "__gnat_setup_communication");
+
+ begin
+ if Internal (Pid.Process'Address) /= 0 then
+ raise Invalid_Process with "cannot setup communication.";
+ end if;
+ end Set_Up_Communications;
+
+ ---------------------------------
+ -- Set_Up_Child_Communications --
+ ---------------------------------
+
+ overriding procedure Set_Up_Child_Communications
+ (Pid : in out TTY_Process_Descriptor;
+ Pipe1 : in out Pipe_Type;
+ Pipe2 : in out Pipe_Type;
+ Pipe3 : in out Pipe_Type;
+ Cmd : String;
+ Args : System.Address)
+ is
+ pragma Unreferenced (Pipe1, Pipe2, Pipe3, Cmd);
+ function Internal
+ (Process : System.Address; Argv : System.Address; Use_Pipes : Integer)
+ return Process_Id;
+ pragma Import (C, Internal, "__gnat_setup_child_communication");
+
+ begin
+ Pid.Pid := Internal (Pid.Process, Args, Boolean'Pos (Pid.Use_Pipes));
+ end Set_Up_Child_Communications;
+
+ ----------------------------------
+ -- Set_Up_Parent_Communications --
+ ----------------------------------
+
+ overriding procedure Set_Up_Parent_Communications
+ (Pid : in out TTY_Process_Descriptor;
+ Pipe1 : in out Pipe_Type;
+ Pipe2 : in out Pipe_Type;
+ Pipe3 : in out Pipe_Type)
+ is
+ pragma Unreferenced (Pipe1, Pipe2, Pipe3);
+
+ procedure Internal
+ (Process : System.Address;
+ Inputfp : out File_Descriptor;
+ Outputfp : out File_Descriptor;
+ Errorfp : out File_Descriptor;
+ Pid : out Process_Id);
+ pragma Import (C, Internal, "__gnat_setup_parent_communication");
+
+ begin
+ Internal
+ (Pid.Process, Pid.Input_Fd, Pid.Output_Fd, Pid.Error_Fd, Pid.Pid);
+ end Set_Up_Parent_Communications;
+
+ -------------------
+ -- Set_Use_Pipes --
+ -------------------
+
+ procedure Set_Use_Pipes
+ (Descriptor : in out TTY_Process_Descriptor;
+ Use_Pipes : Boolean) is
+ begin
+ Descriptor.Use_Pipes := Use_Pipes;
+ end Set_Use_Pipes;
+
+end GNAT.Expect.TTY;
diff --git a/gcc/ada/g-exptty.ads b/gcc/ada/g-exptty.ads
new file mode 100644
index 00000000000..e218e0b5d54
--- /dev/null
+++ b/gcc/ada/g-exptty.ads
@@ -0,0 +1,131 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT LIBRARY COMPONENTS --
+-- --
+-- G N A T . E X P E C T . T T Y --
+-- --
+-- S p e c --
+-- --
+-- 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 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. --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+with GNAT.TTY;
+
+with System;
+with System.OS_Constants;
+
+package GNAT.Expect.TTY is
+
+ pragma Linker_Options (System.OS_Constants.PTY_Library);
+
+ ------------------
+ -- TTY_Process --
+ ------------------
+
+ type TTY_Process_Descriptor is new Process_Descriptor with private;
+ -- Similar to Process_Descriptor, with the parent set up as a full terminal
+ -- (Unix sense, see tty(4)).
+
+ procedure Pseudo_Descriptor
+ (Descriptor : out TTY_Process_Descriptor'Class;
+ TTY : GNAT.TTY.TTY_Handle;
+ Buffer_Size : Natural := 4096);
+ -- Given a terminal descriptor (TTY), create a pseudo process descriptor
+ -- to be used with GNAT.Expect.
+ --
+ -- Note that it is invalid to call Close, Interrupt, Send_Signal on the
+ -- resulting descriptor. To deallocate memory associated with Process,
+ -- call Close_Pseudo_Descriptor instead.
+
+ procedure Close_Pseudo_Descriptor
+ (Descriptor : in out TTY_Process_Descriptor);
+ -- Free memory and ressources associated with Descriptor. Will *not*
+ -- close the associated TTY, it is the caller's responsibility to call
+ -- GNAT.TTY.Close_TTY.
+
+ procedure Interrupt (Pid : Integer);
+ -- Interrupt a process given its pid
+
+ overriding procedure Send
+ (Descriptor : in out TTY_Process_Descriptor;
+ Str : String;
+ Add_LF : Boolean := True;
+ Empty_Buffer : Boolean := False);
+ -- See parent
+ -- What does that comment mean??? what is "parent" here
+
+ procedure Set_Use_Pipes
+ (Descriptor : in out TTY_Process_Descriptor;
+ Use_Pipes : Boolean);
+ -- Tell Expect.TTY whether to use Pipes or Console (on windows). Needs to
+ -- be set before spawning the process. Default is to use Pipes.
+
+ procedure Set_Size
+ (Descriptor : in out TTY_Process_Descriptor'Class;
+ Rows : Natural;
+ Columns : Natural);
+ -- Sets up the size of the terminal as reported to the spawned process
+
+private
+
+ -- All declarations in the private part must be fully commented ???
+
+ overriding procedure Close
+ (Descriptor : in out TTY_Process_Descriptor;
+ Status : out Integer);
+
+ overriding procedure Close
+ (Descriptor : in out TTY_Process_Descriptor);
+
+ overriding procedure Interrupt (Descriptor : in out TTY_Process_Descriptor);
+ -- When we use pseudo-terminals, we do not need to use signals to
+ -- interrupt the debugger, we can simply send the appropriate character.
+ -- This provides a better support for remote debugging for instance.
+
+ procedure Set_Up_Communications
+ (Pid : in out TTY_Process_Descriptor;
+ Err_To_Out : Boolean;
+ Pipe1 : access Pipe_Type;
+ Pipe2 : access Pipe_Type;
+ Pipe3 : access Pipe_Type);
+
+ procedure Set_Up_Parent_Communications
+ (Pid : in out TTY_Process_Descriptor;
+ Pipe1 : in out Pipe_Type;
+ Pipe2 : in out Pipe_Type;
+ Pipe3 : in out Pipe_Type);
+
+ procedure Set_Up_Child_Communications
+ (Pid : in out TTY_Process_Descriptor;
+ Pipe1 : in out Pipe_Type;
+ Pipe2 : in out Pipe_Type;
+ Pipe3 : in out Pipe_Type;
+ Cmd : String;
+ Args : System.Address);
+
+ type TTY_Process_Descriptor is new Process_Descriptor with record
+ Process : System.Address; -- Underlying structure used in C
+ Use_Pipes : Boolean := True;
+ end record;
+
+end GNAT.Expect.TTY;
diff --git a/gcc/ada/g-htable.ads b/gcc/ada/g-htable.ads
index 11f1193d121..28745520645 100644
--- a/gcc/ada/g-htable.ads
+++ b/gcc/ada/g-htable.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1995-2010, AdaCore --
+-- Copyright (C) 1995-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- --
@@ -37,9 +37,7 @@
-- The Static_HTable package provides a more complex interface that allows
-- complete control over allocation.
--- Note: actual code is found in System.HTable (s-htable.ads/adb) since
--- this facility is accessed from run time routines, but clients should
--- always access the version supplied via GNAT.HTable.
+-- See file s-htable.ads for full documentation of the interface
pragma Compiler_Unit;
@@ -51,177 +49,12 @@ package GNAT.HTable is
-- The elaborate body is because we have a dummy body to deal with
-- bootstrap path problems (we used to have a real body, and now we don't
-- need it any more, but the bootstrap requires that we have a dummy body,
- -- since otherwise the old body gets picked up.
-
- -------------------
- -- Simple_HTable --
- -------------------
-
- -- A simple hash table abstraction, easy to instantiate, easy to use.
- -- The table associates one element to one key with the procedure Set.
- -- Get retrieves the Element stored for a given Key. The efficiency of
- -- retrieval is function of the size of the Table parameterized by
- -- Header_Num and the hashing function Hash.
+ -- since otherwise the old body gets picked up; also, we can't use pragma
+ -- No_Body because older bootstrap compilers don't support that).
generic package Simple_HTable renames System.HTable.Simple_HTable;
-
- -- For convenience of reference here is what this package has in it:
-
- -- generic
- -- type Header_Num is range <>;
- -- -- An integer type indicating the number and range of hash headers
-
- -- type Element is private;
- -- -- The type of element to be stored
-
- -- No_Element : Element;
- -- -- The object that is returned by Get when no element has been set
- -- -- for a given key
-
- -- type Key is private;
- -- with function Hash (F : Key) return Header_Num;
- -- with function Equal (F1, F2 : Key) return Boolean;
-
- -- package Simple_HTable is
-
- -- procedure Set (K : Key; E : Element);
- -- -- Associates an element with a given key. Overrides any previously
- -- -- associated element.
-
- -- procedure Reset;
- -- -- Removes and frees all elements in the table
-
- -- function Get (K : Key) return Element;
- -- -- Returns the Element associated with a key or No_Element if the
- -- -- given key has not associated element
-
- -- procedure Remove (K : Key);
- -- -- Removes the latest inserted element pointer associated with the
- -- -- given key if any, does nothing if none.
-
- -- function Get_First return Element;
- -- -- Returns No_Element if the HTable is empty, otherwise returns one
- -- -- non specified element. There is no guarantee that two calls to
- -- -- this function will return the same element.
-
- -- function Get_Next return Element;
- -- -- Returns a non-specified element that has not been returned by the
- -- -- same function since the last call to Get_First or No_Element if
- -- -- there is no such element. If there is no call to 'Set' in between
- -- -- Get_Next calls, all the elements of the HTable will be traversed.
-
- -- procedure Get_First (K : out Key; E : out Element);
- -- -- This version of the iterator returns a key/element pair. A non-
- -- -- specified entry is returned, and there is no guarantee that two
- -- -- calls to this procedure will return the same element.
-
- -- procedure Get_Next (K : out Key; E : out Element);
- -- -- This version of the iterator returns a key/element pair. It
- -- -- returns a non-specified element that has not been returned since
- -- -- the last call to Get_First. If there is no remaining element,
- -- -- then E is set to No_Element, and the value in K is undefined.
- -- -- If there is no call to Set in between Get_Next calls, all the
- -- -- elements of the HTable will be traversed.
-
- -- end Simple_HTable;
-
- -------------------
- -- Static_HTable --
- -------------------
-
- -- A low-level Hash-Table abstraction, not as easy to instantiate as
- -- Simple_HTable but designed to allow complete control over the
- -- allocation of necessary data structures. Particularly useful when
- -- dynamic allocation is not desired. The model is that each Element
- -- contains its own Key that can be retrieved by Get_Key. Furthermore,
- -- Element provides a link that can be used by the HTable for linking
- -- elements with same hash codes:
-
- -- Element
-
- -- +-------------------+
- -- | Key |
- -- +-------------------+
- -- : other data :
- -- +-------------------+
- -- | Next Elmt |
- -- +-------------------+
-
generic package Static_HTable renames System.HTable.Static_HTable;
- -- For convenience of reference here is what this package has in it:
-
- -- generic
- -- type Header_Num is range <>;
- -- -- An integer type indicating the number and range of hash headers.
-
- -- type Element (<>) is limited private;
- -- -- The type of element to be stored
-
- -- type Elmt_Ptr is private;
- -- -- The type used to reference an element (will usually be an
- -- -- access type, but could be some other form of type such as
- -- -- an integer type).
-
- -- Null_Ptr : Elmt_Ptr;
- -- -- The null value of the Elmt_Ptr type.
-
- -- with procedure Set_Next (E : Elmt_Ptr; Next : Elmt_Ptr);
- -- with function Next (E : Elmt_Ptr) return Elmt_Ptr;
- -- -- The type must provide an internal link for the sake of the
- -- -- staticness of the HTable.
-
- -- type Key is limited private;
- -- with function Get_Key (E : Elmt_Ptr) return Key;
- -- with function Hash (F : Key) return Header_Num;
- -- with function Equal (F1, F2 : Key) return Boolean;
-
- -- package Static_HTable is
-
- -- procedure Reset;
- -- -- Resets the hash table by setting all its elements to Null_Ptr.
- -- -- The effect is to clear the hash table so that it can be reused.
- -- -- For the most common case where Elmt_Ptr is an access type, and
- -- -- Null_Ptr is null, this is only needed if the same table is
- -- -- reused in a new context. If Elmt_Ptr is other than an access
- -- -- type, or Null_Ptr is other than null, then Reset must be called
- -- -- before the first use of the hash table.
-
- -- procedure Set (E : Elmt_Ptr);
- -- -- Insert the element pointer in the HTable
-
- -- function Get (K : Key) return Elmt_Ptr;
- -- -- Returns the latest inserted element pointer with the given Key
- -- -- or null if none.
-
- -- procedure Remove (K : Key);
- -- -- Removes the latest inserted element pointer associated with the
- -- -- given key if any, does nothing if none.
-
- -- function Get_First return Elmt_Ptr;
- -- -- Returns Null_Ptr if the HTable is empty, otherwise returns one
- -- -- non specified element. There is no guarantee that two calls to
- -- -- this function will return the same element.
-
- -- function Get_Next return Elmt_Ptr;
- -- -- Returns a non-specified element that has not been returned by
- -- -- the same function since the last call to Get_First or Null_Ptr
- -- -- if there is no such element or Get_First has never been called.
- -- -- If there is no call to 'Set' in between Get_Next calls, all
- -- -- the elements of the HTable will be traversed.
-
- -- end Static_HTable;
-
- ----------
- -- Hash --
- ----------
-
- -- A generic hashing function working on String keys
-
generic function Hash renames System.HTable.Hash;
- -- generic
- -- type Header_Num is range <>;
- -- function Hash (Key : String) return Header_Num;
-
end GNAT.HTable;
diff --git a/gcc/ada/g-tty.adb b/gcc/ada/g-tty.adb
new file mode 100644
index 00000000000..43c1bea5469
--- /dev/null
+++ b/gcc/ada/g-tty.adb
@@ -0,0 +1,134 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT LIBRARY COMPONENTS --
+-- --
+-- G N A T . T T Y --
+-- --
+-- B o d y --
+-- --
+-- 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- --
+-- 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. --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+with Interfaces.C.Strings; use Interfaces.C.Strings;
+
+package body GNAT.TTY is
+
+ use System;
+
+ procedure Check_TTY (Handle : TTY_Handle);
+ -- Check the validity of Handle. Raise Program_Error if ttys are not
+ -- supported. Raise Constraint_Error if Handle is an invalid handle.
+
+ ------------------
+ -- Allocate_TTY --
+ ------------------
+
+ procedure Allocate_TTY (Handle : out TTY_Handle) is
+ function Internal return System.Address;
+ pragma Import (C, Internal, "__gnat_new_tty");
+
+ begin
+ if not TTY_Supported then
+ raise Program_Error;
+ end if;
+
+ Handle.Handle := Internal;
+ end Allocate_TTY;
+
+ ---------------
+ -- Check_TTY --
+ ---------------
+
+ procedure Check_TTY (Handle : TTY_Handle) is
+ begin
+ if not TTY_Supported then
+ raise Program_Error;
+ elsif Handle.Handle = System.Null_Address then
+ raise Constraint_Error;
+ end if;
+ end Check_TTY;
+
+ ---------------
+ -- Close_TTY --
+ ---------------
+
+ procedure Close_TTY (Handle : in out TTY_Handle) is
+ procedure Internal (Handle : System.Address);
+ pragma Import (C, Internal, "__gnat_close_tty");
+ begin
+ Check_TTY (Handle);
+ Internal (Handle.Handle);
+ Handle.Handle := System.Null_Address;
+ end Close_TTY;
+
+ ---------------
+ -- Reset_TTY --
+ ---------------
+
+ procedure Reset_TTY (Handle : TTY_Handle) is
+ procedure Internal (Handle : System.Address);
+ pragma Import (C, Internal, "__gnat_reset_tty");
+ begin
+ Check_TTY (Handle);
+ Internal (Handle.Handle);
+ end Reset_TTY;
+
+ --------------------
+ -- TTY_Descriptor --
+ --------------------
+
+ function TTY_Descriptor
+ (Handle : TTY_Handle) return GNAT.OS_Lib.File_Descriptor
+ is
+ function Internal
+ (Handle : System.Address) return GNAT.OS_Lib.File_Descriptor;
+ pragma Import (C, Internal, "__gnat_tty_fd");
+ begin
+ Check_TTY (Handle);
+ return Internal (Handle.Handle);
+ end TTY_Descriptor;
+
+ --------------
+ -- TTY_Name --
+ --------------
+
+ function TTY_Name (Handle : TTY_Handle) return String is
+ function Internal (Handle : System.Address) return chars_ptr;
+ pragma Import (C, Internal, "__gnat_tty_name");
+ begin
+ Check_TTY (Handle);
+ return Value (Internal (Handle.Handle));
+ end TTY_Name;
+
+ -------------------
+ -- TTY_Supported --
+ -------------------
+
+ function TTY_Supported return Boolean is
+ function Internal return Integer;
+ pragma Import (C, Internal, "__gnat_tty_supported");
+ begin
+ return Internal /= 0;
+ end TTY_Supported;
+
+end GNAT.TTY;
diff --git a/gcc/ada/g-tty.ads b/gcc/ada/g-tty.ads
new file mode 100644
index 00000000000..12aaba760f1
--- /dev/null
+++ b/gcc/ada/g-tty.ads
@@ -0,0 +1,73 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT LIBRARY COMPONENTS --
+-- --
+-- G N A T . T T Y --
+-- --
+-- S p e c --
+-- --
+-- 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- --
+-- 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. --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package provides control over pseudo terminals (ttys)
+
+-- This package is only supported on unix systems. See function TTY_Supported
+-- to test dynamically whether other functions of this package can be called.
+
+with System;
+
+with GNAT.OS_Lib;
+
+package GNAT.TTY is
+
+ type TTY_Handle is private;
+ -- Handle for a tty descriptor
+
+ function TTY_Supported return Boolean;
+ -- If True, the other functions of this package can be called. Otherwise,
+ -- all functions in this package will raise Program_Error if called.
+
+ procedure Allocate_TTY (Handle : out TTY_Handle);
+ -- Allocate a new tty
+
+ procedure Reset_TTY (Handle : TTY_Handle);
+ -- Reset settings of a given tty
+
+ procedure Close_TTY (Handle : in out TTY_Handle);
+ -- Close a given tty
+
+ function TTY_Name (Handle : TTY_Handle) return String;
+ -- Return the external name of a tty. The name depends on the tty handling
+ -- on the given target. It will typically look like: "/dev/ptya1"
+
+ function TTY_Descriptor
+ (Handle : TTY_Handle) return GNAT.OS_Lib.File_Descriptor;
+ -- Return the low level descriptor associated with Handle
+
+private
+
+ type TTY_Handle is record
+ Handle : System.Address := System.Null_Address;
+ end record;
+
+end GNAT.TTY;
diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in
index 4dfc45b6e79..44d75154779 100644
--- a/gcc/ada/gcc-interface/Make-lang.in
+++ b/gcc/ada/gcc-interface/Make-lang.in
@@ -1545,10 +1545,10 @@ ada/checks.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
ada/inline.ads ada/interfac.ads ada/itypes.ads ada/lib.ads ada/lib.adb \
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/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/rtsfind.adb ada/scans.ads \
- ada/sem.ads ada/sem.adb ada/sem_attr.ads ada/sem_aux.ads \
+ ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads 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/rtsfind.adb \
+ ada/scans.ads ada/sem.ads ada/sem.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_ch2.ads ada/sem_ch3.ads \
ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads ada/sem_ch7.ads \
@@ -2544,18 +2544,19 @@ ada/exp_smem.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
ada/hostparm.ads ada/inline.ads ada/interfac.ads ada/lib.ads \
ada/lib-load.ads ada/namet.ads ada/namet.adb ada/nlists.ads \
ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/rtsfind.ads ada/sem.ads ada/sem.adb ada/sem_attr.ads \
- ada/sem_aux.ads ada/sem_aux.adb ada/sem_ch10.ads ada/sem_ch11.ads \
- ada/sem_ch12.ads ada/sem_ch13.ads ada/sem_ch2.ads ada/sem_ch3.ads \
- ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads ada/sem_ch7.ads \
- ada/sem_ch8.ads ada/sem_ch9.ads ada/sem_prag.ads ada/sem_util.ads \
- ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/stringt.adb ada/system.ads ada/s-exctab.ads \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-secsta.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tbuild.ads \
- ada/tree_io.ads ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
+ ada/restrict.ads ada/rident.ads ada/rtsfind.ads ada/sem.ads ada/sem.adb \
+ ada/sem_attr.ads ada/sem_aux.ads ada/sem_aux.adb ada/sem_ch10.ads \
+ ada/sem_ch11.ads ada/sem_ch12.ads ada/sem_ch13.ads ada/sem_ch2.ads \
+ ada/sem_ch3.ads ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads \
+ ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch9.ads ada/sem_prag.ads \
+ ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
+ ada/snames.ads ada/stand.ads ada/stringt.ads ada/stringt.adb \
+ ada/system.ads ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads \
+ ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
+ ada/s-secsta.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
+ ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
+ ada/table.ads ada/table.adb ada/tbuild.ads ada/tree_io.ads \
+ ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
ada/exp_strm.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
@@ -2666,21 +2667,22 @@ ada/expander.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
ada/gnat.ads ada/g-htable.ads ada/gnatvsn.ads ada/hlo.ads \
ada/hostparm.ads ada/inline.ads ada/interfac.ads ada/lib.ads \
ada/lib-load.ads ada/namet.ads ada/namet.adb ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/opt.ads ada/output.ads ada/rident.ads \
- ada/rtsfind.ads ada/scans.ads ada/sem.ads ada/sem.adb ada/sem_attr.ads \
- ada/sem_aux.ads ada/sem_ch10.ads ada/sem_ch11.ads ada/sem_ch12.ads \
- ada/sem_ch13.ads ada/sem_ch2.ads ada/sem_ch3.ads ada/sem_ch4.ads \
- ada/sem_ch5.ads ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads \
- ada/sem_ch9.ads ada/sem_prag.ads ada/sem_util.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/stylesw.ads ada/system.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/targparm.ads ada/tree_io.ads ada/types.ads \
- ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
+ ada/nlists.adb ada/nmake.ads ada/opt.ads ada/output.ads \
+ ada/restrict.ads ada/rident.ads ada/rtsfind.ads ada/scans.ads \
+ ada/sem.ads ada/sem.adb ada/sem_attr.ads ada/sem_aux.ads \
+ ada/sem_ch10.ads ada/sem_ch11.ads ada/sem_ch12.ads ada/sem_ch13.ads \
+ ada/sem_ch2.ads ada/sem_ch3.ads ada/sem_ch4.ads ada/sem_ch5.ads \
+ ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch9.ads \
+ ada/sem_prag.ads ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb \
+ ada/sinput.ads ada/snames.ads ada/stand.ads ada/stylesw.ads \
+ ada/system.ads ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads \
+ ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
+ ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
+ ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
+ ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
+ ada/targparm.ads ada/tree_io.ads ada/types.ads ada/uintp.ads \
+ ada/uintp.adb ada/uname.ads ada/unchconv.ads ada/unchdeal.ads \
+ ada/urealp.ads ada/widechar.ads
ada/fmap.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/fmap.ads ada/fmap.adb \
@@ -2936,21 +2938,22 @@ ada/inline.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
ada/hostparm.ads ada/inline.ads ada/inline.adb ada/interfac.ads \
ada/lib.ads ada/lib.adb ada/lib-list.adb ada/lib-load.ads \
ada/lib-sort.adb ada/namet.ads ada/namet.adb ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/opt.ads ada/output.ads ada/rident.ads \
- ada/scans.ads ada/sem.ads ada/sem.adb ada/sem_attr.ads ada/sem_aux.ads \
- ada/sem_aux.adb ada/sem_ch10.ads ada/sem_ch11.ads ada/sem_ch12.ads \
- ada/sem_ch13.ads ada/sem_ch2.ads ada/sem_ch3.ads ada/sem_ch4.ads \
- ada/sem_ch5.ads ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads \
- ada/sem_ch9.ads ada/sem_prag.ads ada/sem_util.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/stylesw.ads ada/system.ads ada/s-exctab.ads \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/targparm.ads ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
+ ada/nlists.adb ada/nmake.ads ada/opt.ads ada/output.ads \
+ ada/restrict.ads ada/rident.ads ada/scans.ads ada/sem.ads ada/sem.adb \
+ ada/sem_attr.ads ada/sem_aux.ads ada/sem_aux.adb ada/sem_ch10.ads \
+ ada/sem_ch11.ads ada/sem_ch12.ads ada/sem_ch13.ads ada/sem_ch2.ads \
+ ada/sem_ch3.ads ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads \
+ ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch9.ads ada/sem_prag.ads \
+ ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
+ ada/snames.ads ada/stand.ads ada/stringt.ads ada/stylesw.ads \
+ ada/system.ads ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads \
+ ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
+ ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
+ ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
+ ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
+ ada/targparm.ads ada/tree_io.ads ada/types.ads ada/uintp.ads \
+ ada/uintp.adb ada/uname.ads ada/unchconv.ads ada/unchdeal.ads \
+ ada/urealp.ads ada/widechar.ads
ada/interfac.o : ada/interfac.ads ada/system.ads
@@ -2963,19 +2966,19 @@ ada/itypes.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
ada/hostparm.ads ada/inline.ads ada/interfac.ads ada/itypes.ads \
ada/itypes.adb ada/lib.ads ada/lib-load.ads ada/namet.ads ada/namet.adb \
ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/opt.ads ada/output.ads \
- ada/rident.ads ada/sem.ads ada/sem.adb ada/sem_attr.ads \
- ada/sem_ch10.ads ada/sem_ch11.ads ada/sem_ch12.ads ada/sem_ch13.ads \
- ada/sem_ch2.ads ada/sem_ch3.ads ada/sem_ch4.ads ada/sem_ch5.ads \
- ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch9.ads \
- ada/sem_prag.ads ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/stand.ads ada/system.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/targparm.ads ada/tree_io.ads ada/types.ads \
- ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
+ ada/restrict.ads ada/rident.ads ada/sem.ads ada/sem.adb \
+ ada/sem_attr.ads ada/sem_ch10.ads ada/sem_ch11.ads ada/sem_ch12.ads \
+ ada/sem_ch13.ads ada/sem_ch2.ads ada/sem_ch3.ads ada/sem_ch4.ads \
+ ada/sem_ch5.ads ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads \
+ ada/sem_ch9.ads ada/sem_prag.ads ada/sem_util.ads ada/sinfo.ads \
+ ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
+ ada/system.ads ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads \
+ ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
+ ada/s-secsta.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
+ ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
+ ada/table.ads ada/table.adb ada/targparm.ads ada/tree_io.ads \
+ ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
+ ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
ada/krunch.o : ada/ada.ads ada/a-unccon.ads ada/hostparm.ads \
ada/krunch.ads ada/krunch.adb ada/system.ads ada/s-exctab.ads \
@@ -3689,24 +3692,24 @@ ada/sem.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads ada/a-uncdea.ads \
ada/lib.ads ada/lib.adb 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/nlists.ads ada/nlists.adb ada/nmake.ads ada/opt.ads \
- ada/output.ads ada/put_alfa.ads ada/restrict.ads ada/rident.ads \
- ada/rtsfind.ads ada/scans.ads ada/sem.ads ada/sem.adb ada/sem_attr.ads \
- ada/sem_aux.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_ch2.adb \
- ada/sem_ch3.ads ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads \
- ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch9.ads ada/sem_eval.ads \
- ada/sem_prag.ads ada/sem_res.ads ada/sem_type.ads ada/sem_util.ads \
- ada/sem_warn.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/snames.ads ada/stand.ads ada/stringt.ads ada/stylesw.ads \
- ada/system.ads ada/s-carun8.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/targparm.ads ada/tbuild.ads ada/tree_io.ads \
- ada/ttypes.ads ada/types.ads ada/types.adb ada/uintp.ads ada/uintp.adb \
- ada/uname.ads ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads \
- ada/warnsw.ads ada/widechar.ads
+ ada/output.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_attr.ads ada/sem_aux.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_ch2.adb ada/sem_ch3.ads ada/sem_ch4.ads ada/sem_ch5.ads \
+ ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch9.ads \
+ ada/sem_eval.ads ada/sem_prag.ads ada/sem_res.ads ada/sem_type.ads \
+ ada/sem_util.ads ada/sem_warn.ads ada/sinfo.ads ada/sinfo.adb \
+ ada/sinput.ads ada/snames.ads ada/stand.ads ada/stringt.ads \
+ ada/stylesw.ads ada/system.ads ada/s-carun8.ads ada/s-exctab.ads \
+ ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
+ ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
+ ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
+ ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
+ ada/table.ads ada/table.adb ada/targparm.ads ada/tbuild.ads \
+ ada/tree_io.ads ada/ttypes.ads ada/types.ads ada/types.adb \
+ ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
+ ada/unchdeal.ads ada/urealp.ads ada/warnsw.ads ada/widechar.ads
ada/sem_aggr.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
@@ -3812,14 +3815,14 @@ ada/sem_case.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
ada/gnatvsn.ads ada/hlo.ads ada/hostparm.ads ada/inline.ads \
ada/interfac.ads ada/lib.ads ada/lib-load.ads ada/namet.ads \
ada/namet.adb ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb \
- ada/opt.ads ada/output.ads ada/rident.ads ada/scans.ads ada/sem.ads \
- ada/sem.adb ada/sem_attr.ads ada/sem_aux.ads ada/sem_aux.adb \
- ada/sem_case.ads ada/sem_case.adb ada/sem_ch10.ads ada/sem_ch11.ads \
- ada/sem_ch12.ads ada/sem_ch13.ads ada/sem_ch2.ads ada/sem_ch3.ads \
- ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads ada/sem_ch7.ads \
- ada/sem_ch8.ads ada/sem_ch9.ads ada/sem_eval.ads ada/sem_prag.ads \
- ada/sem_res.ads ada/sem_type.ads ada/sem_util.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
+ ada/opt.ads ada/output.ads ada/restrict.ads ada/rident.ads \
+ ada/scans.ads ada/sem.ads ada/sem.adb ada/sem_attr.ads ada/sem_aux.ads \
+ ada/sem_aux.adb ada/sem_case.ads ada/sem_case.adb ada/sem_ch10.ads \
+ ada/sem_ch11.ads ada/sem_ch12.ads ada/sem_ch13.ads ada/sem_ch2.ads \
+ ada/sem_ch3.ads ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads \
+ ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch9.ads ada/sem_eval.ads \
+ ada/sem_prag.ads ada/sem_res.ads ada/sem_type.ads ada/sem_util.ads \
+ ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
ada/stylesw.ads ada/system.ads ada/s-exctab.ads ada/s-htable.ads \
ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
@@ -4242,23 +4245,24 @@ ada/sem_ch8.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
ada/rident.ads ada/rtsfind.ads ada/rtsfind.adb ada/scans.ads \
ada/sem.ads ada/sem.adb ada/sem_aggr.ads 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_ch2.ads \
- ada/sem_ch3.ads ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads \
- ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch8.adb ada/sem_ch9.ads \
- ada/sem_disp.ads ada/sem_dist.ads ada/sem_elab.ads ada/sem_elim.ads \
- ada/sem_eval.ads ada/sem_intr.ads ada/sem_prag.ads ada/sem_res.ads \
- ada/sem_res.adb ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb \
- ada/sem_warn.ads ada/sinfo.ads ada/sinfo.adb ada/sinfo-cn.ads \
- ada/sinput.ads ada/sinput.adb ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/style.ads ada/styleg.ads ada/styleg.adb \
- ada/stylesw.ads ada/system.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/targparm.ads ada/tbuild.ads ada/tree_io.ads \
- ada/ttypes.ads ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.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 ada/sem_ch5.ads \
+ ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch8.adb \
+ ada/sem_ch9.ads ada/sem_disp.ads ada/sem_dist.ads ada/sem_elab.ads \
+ ada/sem_elim.ads ada/sem_eval.ads ada/sem_intr.ads ada/sem_prag.ads \
+ ada/sem_res.ads ada/sem_res.adb ada/sem_type.ads ada/sem_util.ads \
+ ada/sem_util.adb ada/sem_warn.ads ada/sinfo.ads ada/sinfo.adb \
+ ada/sinfo-cn.ads ada/sinput.ads ada/sinput.adb ada/snames.ads \
+ ada/stand.ads ada/stringt.ads ada/style.ads ada/styleg.ads \
+ ada/styleg.adb ada/stylesw.ads ada/system.ads ada/s-exctab.ads \
+ ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
+ ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
+ ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
+ ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
+ ada/table.ads ada/table.adb ada/targparm.ads ada/tbuild.ads \
+ ada/tree_io.ads ada/ttypes.ads ada/types.ads ada/uintp.ads \
+ ada/uintp.adb ada/uname.ads ada/unchconv.ads ada/unchdeal.ads \
+ ada/urealp.ads ada/warnsw.ads ada/widechar.ads
ada/sem_ch9.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
@@ -4345,23 +4349,23 @@ ada/sem_dist.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
ada/hostparm.ads ada/inline.ads ada/interfac.ads ada/lib.ads \
ada/lib-load.ads ada/namet.ads ada/namet.adb ada/nlists.ads \
ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/rident.ads ada/rtsfind.ads ada/scans.ads ada/sem.ads ada/sem.adb \
- ada/sem_attr.ads ada/sem_aux.ads ada/sem_aux.adb ada/sem_ch10.ads \
- ada/sem_ch11.ads ada/sem_ch12.ads ada/sem_ch13.ads ada/sem_ch2.ads \
- ada/sem_ch3.ads ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads \
- ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch9.ads ada/sem_disp.ads \
- ada/sem_dist.ads ada/sem_dist.adb ada/sem_eval.ads ada/sem_prag.ads \
- ada/sem_res.ads ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/stand.ads ada/stringt.ads \
- ada/stringt.adb ada/stylesw.ads ada/system.ads ada/s-carun8.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tbuild.ads ada/tree_io.ads ada/types.ads ada/types.adb \
- ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
+ ada/restrict.ads ada/rident.ads ada/rtsfind.ads ada/scans.ads \
+ ada/sem.ads ada/sem.adb ada/sem_attr.ads ada/sem_aux.ads \
+ ada/sem_aux.adb ada/sem_ch10.ads ada/sem_ch11.ads ada/sem_ch12.ads \
+ ada/sem_ch13.ads ada/sem_ch2.ads ada/sem_ch3.ads ada/sem_ch4.ads \
+ ada/sem_ch5.ads ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads \
+ ada/sem_ch9.ads ada/sem_disp.ads ada/sem_dist.ads ada/sem_dist.adb \
+ ada/sem_eval.ads ada/sem_prag.ads ada/sem_res.ads ada/sem_util.ads \
+ ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
+ ada/stringt.ads ada/stringt.adb ada/stylesw.ads ada/system.ads \
+ ada/s-carun8.ads ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads \
+ ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
+ ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
+ ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
+ ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
+ ada/targparm.ads ada/tbuild.ads ada/tree_io.ads ada/types.ads \
+ ada/types.adb ada/uintp.ads ada/uintp.adb ada/uname.ads \
+ ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
ada/sem_elab.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
@@ -4409,22 +4413,23 @@ ada/sem_elim.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
ada/hlo.ads ada/hostparm.ads ada/inline.ads ada/interfac.ads \
ada/lib.ads ada/lib.adb ada/lib-list.adb ada/lib-load.ads \
ada/lib-sort.adb ada/namet.ads ada/namet.adb ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/opt.ads ada/output.ads ada/rident.ads \
- ada/scans.ads ada/sem.ads ada/sem.adb ada/sem_attr.ads ada/sem_aux.ads \
- ada/sem_aux.adb ada/sem_ch10.ads ada/sem_ch11.ads ada/sem_ch12.ads \
- ada/sem_ch13.ads ada/sem_ch2.ads ada/sem_ch3.ads ada/sem_ch4.ads \
- ada/sem_ch5.ads ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads \
- ada/sem_ch9.ads ada/sem_elim.ads ada/sem_elim.adb ada/sem_prag.ads \
- ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/sinput.adb ada/snames.ads ada/stand.ads ada/stringt.ads \
- ada/stylesw.ads ada/system.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-htable.adb ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-strhas.ads ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tree_io.ads ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
+ ada/nlists.adb ada/nmake.ads ada/opt.ads ada/output.ads \
+ ada/restrict.ads ada/rident.ads ada/scans.ads ada/sem.ads ada/sem.adb \
+ ada/sem_attr.ads ada/sem_aux.ads ada/sem_aux.adb ada/sem_ch10.ads \
+ ada/sem_ch11.ads ada/sem_ch12.ads ada/sem_ch13.ads ada/sem_ch2.ads \
+ ada/sem_ch3.ads ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads \
+ ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch9.ads ada/sem_elim.ads \
+ ada/sem_elim.adb ada/sem_prag.ads ada/sem_util.ads ada/sinfo.ads \
+ ada/sinfo.adb ada/sinput.ads ada/sinput.adb ada/snames.ads \
+ ada/stand.ads ada/stringt.ads ada/stylesw.ads ada/system.ads \
+ ada/s-exctab.ads ada/s-htable.ads ada/s-htable.adb ada/s-imenne.ads \
+ ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
+ ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
+ ada/s-stoele.ads ada/s-stoele.adb ada/s-strhas.ads ada/s-string.ads \
+ ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
+ ada/table.adb ada/targparm.ads ada/tree_io.ads ada/types.ads \
+ ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
+ ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
ada/sem_eval.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
@@ -4494,21 +4499,22 @@ ada/sem_mech.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
ada/gnat.ads ada/g-htable.ads ada/gnatvsn.ads ada/hlo.ads \
ada/hostparm.ads ada/inline.ads ada/interfac.ads ada/lib.ads \
ada/lib-load.ads ada/namet.ads ada/namet.adb ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/opt.ads ada/output.ads ada/rident.ads \
- ada/scans.ads ada/sem.ads ada/sem.adb ada/sem_attr.ads ada/sem_aux.ads \
- ada/sem_aux.adb ada/sem_ch10.ads ada/sem_ch11.ads ada/sem_ch12.ads \
- ada/sem_ch13.ads ada/sem_ch2.ads ada/sem_ch3.ads ada/sem_ch4.ads \
- ada/sem_ch5.ads ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads \
- ada/sem_ch9.ads ada/sem_mech.ads ada/sem_mech.adb ada/sem_prag.ads \
- ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/snames.ads ada/stand.ads ada/stylesw.ads ada/system.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tree_io.ads ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
+ ada/nlists.adb ada/nmake.ads ada/opt.ads ada/output.ads \
+ ada/restrict.ads ada/rident.ads ada/scans.ads ada/sem.ads ada/sem.adb \
+ ada/sem_attr.ads ada/sem_aux.ads ada/sem_aux.adb ada/sem_ch10.ads \
+ ada/sem_ch11.ads ada/sem_ch12.ads ada/sem_ch13.ads ada/sem_ch2.ads \
+ ada/sem_ch3.ads ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads \
+ ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch9.ads ada/sem_mech.ads \
+ ada/sem_mech.adb ada/sem_prag.ads ada/sem_util.ads ada/sinfo.ads \
+ ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
+ ada/stylesw.ads ada/system.ads ada/s-exctab.ads ada/s-htable.ads \
+ ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
+ ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
+ ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
+ ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
+ ada/table.adb ada/targparm.ads ada/tree_io.ads ada/types.ads \
+ ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
+ ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
ada/sem_prag.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
ada/a-uncdea.ads ada/ali.ads ada/alloc.ads ada/aspects.ads \
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in
index d000b5df779..ad8917fcd29 100644
--- a/gcc/ada/gcc-interface/Makefile.in
+++ b/gcc/ada/gcc-interface/Makefile.in
@@ -273,15 +273,9 @@ INCLUDES = -I- -I. -I.. -I$(srcdir)/ada -I$(srcdir) -I$(srcdir)/config \
ADA_INCLUDES = -I- -I. -I$(srcdir)/ada
-INCLUDES_FOR_SUBDIR = -iquote . -iquote .. -iquote ../.. -iquote $(fsrcdir)/ada \
- -I$(fsrcdir)/../include
-
-ifeq ($(strip $(filter-out cygwin32% mingw32% pe,$(osys))),)
- # On Windows native the tconfig.h files used by C runtime files needs to have
- # the gcc source dir in its include dir list
- INCLUDES_FOR_SUBDIR = -iquote . -iquote .. -iquote ../.. -iquote $(fsrcdir)/ada \
- -I$(fsrcdir)/../include -I$(fsrcdir)
-endif
+INCLUDES_FOR_SUBDIR = -iquote . -iquote .. -iquote ../.. \
+ -iquote $(fsrcdir)/ada -iquote $(fsrcdir) \
+ -I$(fsrcdir)/../include
ADA_INCLUDES_FOR_SUBDIR = -I. -I$(fsrcdir)/ada
@@ -1162,6 +1156,7 @@ ifeq ($(strip $(filter-out %86 kfreebsd%,$(arch) $(osys))),)
GNATLIB_SHARED = gnatlib-shared-dual
GMEM_LIB = gmemlib
LIBRARY_VERSION := $(LIB_VERSION)
+ MISCLIB = -lutil
endif
ifeq ($(strip $(filter-out x86_64 kfreebsd%,$(arch) $(osys))),)
@@ -1215,6 +1210,7 @@ ifeq ($(strip $(filter-out %86 freebsd%,$(arch) $(osys))),)
THREADSLIB= -lpthread
GMEM_LIB = gmemlib
LIBRARY_VERSION := $(LIB_VERSION)
+ MISCLIB = -lutil
endif
ifeq ($(strip $(filter-out %86_64 freebsd%,$(arch) $(osys))),)
@@ -1241,6 +1237,7 @@ ifeq ($(strip $(filter-out %86_64 freebsd%,$(arch) $(osys))),)
THREADSLIB= -lpthread
GMEM_LIB = gmemlib
LIBRARY_VERSION := $(LIB_VERSION)
+ MISCLIB = -lutil
endif
ifeq ($(strip $(filter-out s390% linux%,$(arch) $(osys))),)
@@ -2182,7 +2179,6 @@ ifeq ($(strip $(filter-out darwin%,$(osys))),)
EH_MECHANISM=-gcc
GNATLIB_SHARED = gnatlib-shared-darwin
- RANLIB = ranlib -c
GMEM_LIB = gmemlib
LIBRARY_VERSION := $(LIB_VERSION)
soext = .dylib
@@ -2220,12 +2216,13 @@ LIBGNAT_SRCS = adadecode.c adadecode.h adaint.c adaint.h \
argv.c cio.c cstreams.c errno.c exit.c cal.c ctrl_c.c env.c env.h \
arit64.c raise.h raise.c sysdep.c aux-io.c init.c initialize.c \
locales.c seh_init.c final.c tracebak.c tb-alvms.c tb-alvxw.c \
- tb-gcc.c expect.c mkdir.c socket.c gsocket.h targext.c $(EXTRA_LIBGNAT_SRCS)
+ tb-gcc.c expect.c mkdir.c socket.c gsocket.h targext.c \
+ terminals.c $(EXTRA_LIBGNAT_SRCS)
LIBGNAT_OBJS = adadecode.o adaint.o argv.o cio.o cstreams.o ctrl_c.o \
errno.o exit.o env.o raise.o sysdep.o aux-io.o init.o initialize.o \
locales.o seh_init.o cal.o arit64.o final.o tracebak.o expect.o \
- mkdir.o socket.o targext.o $(EXTRA_LIBGNAT_OBJS)
+ mkdir.o socket.o targext.o terminals.o $(EXTRA_LIBGNAT_OBJS)
# NOTE ??? - when the -I option for compiling Ada code is made to work,
# the library installation will change and there will be a
@@ -2866,6 +2863,7 @@ socket.o : socket.c gsocket.h
sysdep.o : sysdep.c
raise.o : raise.c raise.h
sigtramp-ppcvxw.o : sigtramp-ppcvxw.c sigtramp.h
+terminals.o : terminals.c
vx_stack_info.o : vx_stack_info.c
raise-gcc.o : raise-gcc.c raise.h
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index d7ca5dbbe6e..12971a63038 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -160,7 +160,7 @@ static bool compile_time_known_address_p (Node_Id);
static bool cannot_be_superflat_p (Node_Id);
static bool constructor_address_p (tree);
static void components_to_record (tree, Node_Id, tree, int, bool, bool, bool,
- bool, bool, bool, bool, tree *);
+ bool, bool, bool, bool, tree, tree *);
static Uint annotate_value (tree);
static void annotate_rep (Entity_Id, tree);
static tree build_position_list (tree, bool, tree, tree, unsigned int, tree);
@@ -176,6 +176,7 @@ static unsigned int ceil_alignment (unsigned HOST_WIDE_INT);
static void check_ok_for_atomic (tree, Entity_Id, bool);
static tree create_field_decl_from (tree, tree, tree, tree, tree,
VEC(subst_pair,heap) *);
+static tree create_rep_part (tree, tree, tree);
static tree get_rep_part (tree);
static tree create_variant_part_from (tree, VEC(variant_desc,heap) *, tree,
tree, VEC(subst_pair,heap) *);
@@ -3048,7 +3049,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
gnu_field_list, packed, definition, false,
all_rep, is_unchecked_union, debug_info_p,
false, OK_To_Reorder_Components (gnat_entity),
- NULL);
+ all_rep ? NULL_TREE : bitsize_zero_node, NULL);
/* If it is passed by reference, force BLKmode to ensure that objects
of this type will always be put in memory. */
@@ -7096,6 +7097,10 @@ compare_field_bitpos (const PTR rt1, const PTR rt2)
REORDER is true if we are permitted to reorder components of this type.
+ FIRST_FREE_POS, if nonzero, is the first (lowest) free field position in
+ the outer record type down to this variant level. It is nonzero only if
+ all the fields down to this level have a rep clause and ALL_REP is false.
+
P_GNU_REP_LIST, if nonzero, is a pointer to a list to which each field
with a rep clause is to be added; in this case, that is all that should
be done with such fields. */
@@ -7106,12 +7111,13 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
bool cancel_alignment, bool all_rep,
bool unchecked_union, bool debug_info,
bool maybe_unused, bool reorder,
- tree *p_gnu_rep_list)
+ tree first_free_pos, tree *p_gnu_rep_list)
{
bool all_rep_and_size = all_rep && TYPE_SIZE (gnu_record_type);
bool layout_with_rep = false;
Node_Id component_decl, variant_part;
tree gnu_field, gnu_next, gnu_last;
+ tree gnu_rep_part = NULL_TREE;
tree gnu_variant_part = NULL_TREE;
tree gnu_rep_list = NULL_TREE;
tree gnu_var_list = NULL_TREE;
@@ -7185,7 +7191,7 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
= concat_name (get_identifier (Get_Name_String (Chars (gnat_discr))),
"XVN");
tree gnu_union_type, gnu_union_name;
- tree gnu_variant_list = NULL_TREE;
+ tree this_first_free_pos, gnu_variant_list = NULL_TREE;
if (TREE_CODE (gnu_name) == TYPE_DECL)
gnu_name = DECL_NAME (gnu_name);
@@ -7193,12 +7199,10 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
gnu_union_name
= concat_name (gnu_name, IDENTIFIER_POINTER (gnu_var_name));
- /* Reuse an enclosing union if all fields are in the variant part
- and there is no representation clause on the record, to match
- the layout of C unions. There is an associated check below. */
- if (!gnu_field_list
- && TREE_CODE (gnu_record_type) == UNION_TYPE
- && !TYPE_PACKED (gnu_record_type))
+ /* Reuse the enclosing union if this is an Unchecked_Union whose fields
+ are all in the variant part, to match the layout of C unions. There
+ is an associated check below. */
+ if (TREE_CODE (gnu_record_type) == UNION_TYPE)
gnu_union_type = gnu_record_type;
else
{
@@ -7210,6 +7214,29 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
TYPE_PACKED (gnu_union_type) = TYPE_PACKED (gnu_record_type);
}
+ /* If all the fields down to this level have a rep clause, find out
+ whether all the fields at this level also have one. If so, then
+ compute the new first free position to be passed downward. */
+ this_first_free_pos = first_free_pos;
+ if (this_first_free_pos)
+ {
+ for (gnu_field = gnu_field_list;
+ gnu_field;
+ gnu_field = DECL_CHAIN (gnu_field))
+ if (DECL_FIELD_OFFSET (gnu_field))
+ {
+ tree pos = bit_position (gnu_field);
+ if (!tree_int_cst_lt (pos, this_first_free_pos))
+ this_first_free_pos
+ = size_binop (PLUS_EXPR, pos, DECL_SIZE (gnu_field));
+ }
+ else
+ {
+ this_first_free_pos = NULL_TREE;
+ break;
+ }
+ }
+
for (variant = First_Non_Pragma (Variants (variant_part));
Present (variant);
variant = Next_Non_Pragma (variant))
@@ -7231,8 +7258,7 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
TYPE_PACKED (gnu_variant_type) = TYPE_PACKED (gnu_record_type);
/* Similarly, if the outer record has a size specified and all
- fields have record rep clauses, we can propagate the size
- into the variant part. */
+ the fields have a rep clause, we can propagate the size. */
if (all_rep_and_size)
{
TYPE_SIZE (gnu_variant_type) = TYPE_SIZE (gnu_record_type);
@@ -7244,20 +7270,24 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
we aren't sure to really use it at this point, see below. */
components_to_record (gnu_variant_type, Component_List (variant),
NULL_TREE, packed, definition,
- !all_rep_and_size, all_rep,
- unchecked_union, debug_info,
- true, reorder, &gnu_rep_list);
+ !all_rep_and_size, all_rep, unchecked_union,
+ debug_info, true, reorder, this_first_free_pos,
+ all_rep || this_first_free_pos
+ ? NULL : &gnu_rep_list);
gnu_qual = choices_to_gnu (gnu_discr, Discrete_Choices (variant));
-
Set_Present_Expr (variant, annotate_value (gnu_qual));
- /* If this is an Unchecked_Union and we have exactly one field,
- use this field directly to match the layout of C unions. */
- if (unchecked_union
- && TYPE_FIELDS (gnu_variant_type)
- && !DECL_CHAIN (TYPE_FIELDS (gnu_variant_type)))
- gnu_field = TYPE_FIELDS (gnu_variant_type);
+ /* If this is an Unchecked_Union whose fields are all in the variant
+ part and we have a single field with no representation clause or
+ placed at offset zero, use the field directly to match the layout
+ of C unions. */
+ if (TREE_CODE (gnu_record_type) == UNION_TYPE
+ && (gnu_field = TYPE_FIELDS (gnu_variant_type)) != NULL_TREE
+ && !DECL_CHAIN (gnu_field)
+ && (!DECL_FIELD_OFFSET (gnu_field)
+ || integer_zerop (bit_position (gnu_field))))
+ DECL_CONTEXT (gnu_field) = gnu_union_type;
else
{
/* Deal with packedness like in gnat_to_gnu_field. */
@@ -7328,15 +7358,18 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
gnu_variant_part
= create_field_decl (gnu_var_name, gnu_union_type, gnu_record_type,
all_rep ? TYPE_SIZE (gnu_union_type) : 0,
- all_rep ? bitsize_zero_node : 0,
+ all_rep || this_first_free_pos
+ ? bitsize_zero_node : 0,
union_field_packed, 0);
DECL_INTERNAL_P (gnu_variant_part) = 1;
- DECL_CHAIN (gnu_variant_part) = gnu_field_list;
- gnu_field_list = gnu_variant_part;
}
}
+ /* From now on, a zero FIRST_FREE_POS is totally useless. */
+ if (first_free_pos && integer_zerop (first_free_pos))
+ first_free_pos = NULL_TREE;
+
/* Scan GNU_FIELD_LIST and see if any fields have rep clauses and, if we are
permitted to reorder components, self-referential sizes or variable sizes.
If they do, pull them out and put them onto the appropriate list. We have
@@ -7368,33 +7401,24 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
continue;
}
- if (reorder)
+ /* Reorder non-internal fields with non-fixed size. */
+ if (reorder
+ && !DECL_INTERNAL_P (gnu_field)
+ && !(DECL_SIZE (gnu_field)
+ && TREE_CODE (DECL_SIZE (gnu_field)) == INTEGER_CST))
{
- /* Pull out the variant part and put it onto GNU_SELF_LIST. */
- if (gnu_field == gnu_variant_part)
+ tree type_size = TYPE_SIZE (TREE_TYPE (gnu_field));
+
+ if (CONTAINS_PLACEHOLDER_P (type_size))
{
MOVE_FROM_FIELD_LIST_TO (gnu_self_list);
continue;
}
- /* Skip internal fields and fields with fixed size. */
- if (!DECL_INTERNAL_P (gnu_field)
- && !(DECL_SIZE (gnu_field)
- && TREE_CODE (DECL_SIZE (gnu_field)) == INTEGER_CST))
+ if (TREE_CODE (type_size) != INTEGER_CST)
{
- tree type_size = TYPE_SIZE (TREE_TYPE (gnu_field));
-
- if (CONTAINS_PLACEHOLDER_P (type_size))
- {
- MOVE_FROM_FIELD_LIST_TO (gnu_self_list);
- continue;
- }
-
- if (TREE_CODE (type_size) != INTEGER_CST)
- {
- MOVE_FROM_FIELD_LIST_TO (gnu_var_list);
- continue;
- }
+ MOVE_FROM_FIELD_LIST_TO (gnu_var_list);
+ continue;
}
}
@@ -7416,14 +7440,14 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
= chainon (nreverse (gnu_self_list),
chainon (nreverse (gnu_var_list), gnu_field_list));
- /* If we have any fields in our rep'ed field list and it is not the case that
- all the fields in the record have rep clauses and P_REP_LIST is nonzero,
- set it and ignore these fields. */
- if (gnu_rep_list && p_gnu_rep_list && !all_rep)
+ /* If P_REP_LIST is nonzero, this means that we are asked to move the fields
+ in our REP list to the previous level because this level needs them in
+ order to do a correct layout, i.e. avoid having overlapping fields. */
+ if (p_gnu_rep_list && gnu_rep_list)
*p_gnu_rep_list = chainon (*p_gnu_rep_list, gnu_rep_list);
/* Otherwise, sort the fields by bit position and put them into their own
- record, before the others, if we also have fields without rep clauses. */
+ record, before the others, if we also have fields without rep clause. */
else if (gnu_rep_list)
{
tree gnu_rep_type
@@ -7451,11 +7475,12 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
if (gnu_field_list)
{
finish_record_type (gnu_rep_type, gnu_rep_list, 1, debug_info);
- gnu_field
- = create_field_decl (get_identifier ("REP"), gnu_rep_type,
- gnu_record_type, NULL_TREE, NULL_TREE, 0, 1);
- DECL_INTERNAL_P (gnu_field) = 1;
- gnu_field_list = chainon (gnu_field_list, gnu_field);
+
+ /* If FIRST_FREE_POS is nonzero, we need to ensure that the fields
+ without rep clause are laid out starting from this position.
+ Therefore, we force it as a minimal size on the REP part. */
+ gnu_rep_part
+ = create_rep_part (gnu_rep_type, gnu_record_type, first_free_pos);
}
else
{
@@ -7464,6 +7489,28 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
}
}
+ /* If FIRST_FREE_POS is nonzero, we need to ensure that the fields without
+ rep clause are laid out starting from this position. Therefore, if we
+ have not already done so, we create a fake REP part with this size. */
+ if (first_free_pos && !layout_with_rep && !gnu_rep_part)
+ {
+ tree gnu_rep_type = make_node (RECORD_TYPE);
+ finish_record_type (gnu_rep_type, NULL_TREE, 0, debug_info);
+ gnu_rep_part
+ = create_rep_part (gnu_rep_type, gnu_record_type, first_free_pos);
+ }
+
+ /* Now chain the REP part at the end of the reversed field list. */
+ if (gnu_rep_part)
+ gnu_field_list = chainon (gnu_field_list, gnu_rep_part);
+
+ /* And the variant part at the beginning. */
+ if (gnu_variant_part)
+ {
+ DECL_CHAIN (gnu_variant_part) = gnu_field_list;
+ gnu_field_list = gnu_variant_part;
+ }
+
if (cancel_alignment)
TYPE_ALIGN (gnu_record_type) = 0;
@@ -8567,6 +8614,24 @@ create_field_decl_from (tree old_field, tree field_type, tree record_type,
return new_field;
}
+/* Create the REP part of RECORD_TYPE with REP_TYPE. If MIN_SIZE is nonzero,
+ it is the minimal size the REP_PART must have. */
+
+static tree
+create_rep_part (tree rep_type, tree record_type, tree min_size)
+{
+ tree field;
+
+ if (min_size && !tree_int_cst_lt (TYPE_SIZE (rep_type), min_size))
+ min_size = NULL_TREE;
+
+ field = create_field_decl (get_identifier ("REP"), rep_type, record_type,
+ min_size, bitsize_zero_node, 0, 1);
+ DECL_INTERNAL_P (field) = 1;
+
+ return field;
+}
+
/* Return the REP part of RECORD_TYPE, if any. Otherwise return NULL. */
static tree
@@ -8575,10 +8640,10 @@ get_rep_part (tree record_type)
tree field = TYPE_FIELDS (record_type);
/* The REP part is the first field, internal, another record, and its name
- doesn't start with an underscore (i.e. is not generated by the FE). */
+ starts with an 'R'. */
if (DECL_INTERNAL_P (field)
&& TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
- && IDENTIFIER_POINTER (DECL_NAME (field)) [0] != '_')
+ && IDENTIFIER_POINTER (DECL_NAME (field)) [0] == 'R')
return field;
return NULL_TREE;
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 8a74e6ccb45..42b4e9154c3 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -129,6 +129,7 @@ struct GTY(()) language_function {
VEC(parm_attr,gc) *parm_attr_cache;
bitmap named_ret_val;
VEC(tree,gc) *other_ret_val;
+ int gnat_ret;
};
#define f_parm_attr_cache \
@@ -140,6 +141,9 @@ struct GTY(()) language_function {
#define f_other_ret_val \
DECL_STRUCT_FUNCTION (current_function_decl)->language->other_ret_val
+#define f_gnat_ret \
+ DECL_STRUCT_FUNCTION (current_function_decl)->language->gnat_ret
+
/* A structure used to gather together information about a statement group.
We use this to gather related statements, for example the "then" part
of a IF. In the case where it represents a lexical scope, we may also
@@ -2674,12 +2678,20 @@ establish_gnat_vms_condition_handler (void)
first list. These are the Named Return Values.
4. Adjust the relevant RETURN_EXPRs and replace the occurrences of the
- Named Return Values in the function with the RESULT_DECL. */
+ Named Return Values in the function with the RESULT_DECL.
+
+ If the function returns an unconstrained type, things are a bit different
+ because the anonymous return object is allocated on the secondary stack
+ and RESULT_DECL is only a pointer to it. Each return object can be of a
+ different size and is allocated separately so we need not care about the
+ aforementioned overlapping issues. Therefore, we don't collect the other
+ expressions and skip step #2 in the algorithm. */
struct nrv_data
{
bitmap nrv;
tree result;
+ Node_Id gnat_ret;
struct pointer_set_t *visited;
};
@@ -2812,8 +2824,153 @@ finalize_nrv_r (tree *tp, int *walk_subtrees, void *data)
*tp = convert (TREE_TYPE (t), dp->result);
/* Avoid walking into the same tree more than once. Unfortunately, we
- can't just use walk_tree_without_duplicates because it would only call
- us for the first occurrence of NRVs in the function body. */
+ can't just use walk_tree_without_duplicates because it would only
+ call us for the first occurrence of NRVs in the function body. */
+ if (pointer_set_insert (dp->visited, *tp))
+ *walk_subtrees = 0;
+
+ return NULL_TREE;
+}
+
+/* Likewise, but used when the function returns an unconstrained type. */
+
+static tree
+finalize_nrv_unc_r (tree *tp, int *walk_subtrees, void *data)
+{
+ struct nrv_data *dp = (struct nrv_data *)data;
+ tree t = *tp;
+
+ /* No need to walk into types. */
+ if (TYPE_P (t))
+ *walk_subtrees = 0;
+
+ /* We need to see the DECL_EXPR of NRVs before any other references so we
+ walk the body of BIND_EXPR before walking its variables. */
+ else if (TREE_CODE (t) == BIND_EXPR)
+ walk_tree (&BIND_EXPR_BODY (t), finalize_nrv_unc_r, data, NULL);
+
+ /* Change RETURN_EXPRs of NRVs to assign to the RESULT_DECL only the final
+ return value built by the allocator instead of the whole construct. */
+ else if (TREE_CODE (t) == RETURN_EXPR
+ && TREE_CODE (TREE_OPERAND (t, 0)) == MODIFY_EXPR)
+ {
+ tree ret_val = TREE_OPERAND (TREE_OPERAND (t, 0), 1);
+
+ /* This is the construct returned by the allocator. */
+ if (TREE_CODE (ret_val) == COMPOUND_EXPR
+ && TREE_CODE (TREE_OPERAND (ret_val, 0)) == INIT_EXPR)
+ {
+ if (TYPE_IS_FAT_POINTER_P (TREE_TYPE (ret_val)))
+ ret_val
+ = VEC_index (constructor_elt,
+ CONSTRUCTOR_ELTS
+ (TREE_OPERAND (TREE_OPERAND (ret_val, 0), 1)),
+ 1)->value;
+ else
+ ret_val = TREE_OPERAND (TREE_OPERAND (ret_val, 0), 1);
+ }
+
+ /* Strip useless conversions around the return value. */
+ if (gnat_useless_type_conversion (ret_val)
+ || TREE_CODE (ret_val) == VIEW_CONVERT_EXPR)
+ ret_val = TREE_OPERAND (ret_val, 0);
+
+ /* Strip unpadding around the return value. */
+ if (TREE_CODE (ret_val) == COMPONENT_REF
+ && TYPE_IS_PADDING_P (TREE_TYPE (TREE_OPERAND (ret_val, 0))))
+ ret_val = TREE_OPERAND (ret_val, 0);
+
+ /* Assign the new return value to the RESULT_DECL. */
+ if (is_nrv_p (dp->nrv, ret_val))
+ TREE_OPERAND (TREE_OPERAND (t, 0), 1)
+ = TREE_OPERAND (DECL_INITIAL (ret_val), 0);
+ }
+
+ /* Adjust the DECL_EXPR of NRVs to call the allocator and save the result
+ into a new variable. */
+ else if (TREE_CODE (t) == DECL_EXPR
+ && is_nrv_p (dp->nrv, DECL_EXPR_DECL (t)))
+ {
+ tree saved_current_function_decl = current_function_decl;
+ tree var = DECL_EXPR_DECL (t);
+ tree alloc, p_array, new_var, new_ret;
+ VEC(constructor_elt,gc) *v = VEC_alloc (constructor_elt, gc, 2);
+
+ /* Create an artificial context to build the allocation. */
+ current_function_decl = decl_function_context (var);
+ start_stmt_group ();
+ gnat_pushlevel ();
+
+ /* This will return a COMPOUND_EXPR with the allocation in the first
+ arm and the final return value in the second arm. */
+ alloc = build_allocator (TREE_TYPE (var), DECL_INITIAL (var),
+ TREE_TYPE (dp->result),
+ Procedure_To_Call (dp->gnat_ret),
+ Storage_Pool (dp->gnat_ret),
+ Empty, false);
+
+ /* The new variable is built as a reference to the allocated space. */
+ new_var
+ = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, DECL_NAME (var),
+ build_reference_type (TREE_TYPE (var)));
+ DECL_BY_REFERENCE (new_var) = 1;
+
+ if (TYPE_IS_FAT_POINTER_P (TREE_TYPE (alloc)))
+ {
+ /* The new initial value is a COMPOUND_EXPR with the allocation in
+ the first arm and the value of P_ARRAY in the second arm. */
+ DECL_INITIAL (new_var)
+ = build2 (COMPOUND_EXPR, TREE_TYPE (new_var),
+ TREE_OPERAND (alloc, 0),
+ VEC_index (constructor_elt,
+ CONSTRUCTOR_ELTS (TREE_OPERAND (alloc, 1)),
+ 0)->value);
+
+ /* Build a modified CONSTRUCTOR that references NEW_VAR. */
+ p_array = TYPE_FIELDS (TREE_TYPE (alloc));
+ CONSTRUCTOR_APPEND_ELT (v, p_array,
+ fold_convert (TREE_TYPE (p_array), new_var));
+ CONSTRUCTOR_APPEND_ELT (v, DECL_CHAIN (p_array),
+ VEC_index (constructor_elt,
+ CONSTRUCTOR_ELTS
+ (TREE_OPERAND (alloc, 1)),
+ 1)->value);
+ new_ret = build_constructor (TREE_TYPE (alloc), v);
+ }
+ else
+ {
+ /* The new initial value is just the allocation. */
+ DECL_INITIAL (new_var) = alloc;
+ new_ret = fold_convert (TREE_TYPE (alloc), new_var);
+ }
+
+ gnat_pushdecl (new_var, Empty);
+
+ /* Destroy the artificial context and insert the new statements. */
+ gnat_zaplevel ();
+ *tp = end_stmt_group ();
+ current_function_decl = saved_current_function_decl;
+
+ /* Chain NEW_VAR immediately after VAR and ignore the latter. */
+ DECL_CHAIN (new_var) = DECL_CHAIN (var);
+ DECL_CHAIN (var) = new_var;
+ DECL_IGNORED_P (var) = 1;
+
+ /* Save the new return value and the dereference of NEW_VAR. */
+ DECL_INITIAL (var)
+ = build2 (COMPOUND_EXPR, TREE_TYPE (var), new_ret,
+ build1 (INDIRECT_REF, TREE_TYPE (var), new_var));
+ /* ??? Kludge to avoid messing up during inlining. */
+ DECL_CONTEXT (var) = NULL_TREE;
+ }
+
+ /* And replace all uses of NRVs with the dereference of NEW_VAR. */
+ else if (is_nrv_p (dp->nrv, t))
+ *tp = TREE_OPERAND (DECL_INITIAL (t), 1);
+
+ /* Avoid walking into the same tree more than once. Unfortunately, we
+ can't just use walk_tree_without_duplicates because it would only
+ call us for the first occurrence of NRVs in the function body. */
if (pointer_set_insert (dp->visited, *tp))
*walk_subtrees = 0;
@@ -2822,13 +2979,14 @@ finalize_nrv_r (tree *tp, int *walk_subtrees, void *data)
/* Finalize the Named Return Value optimization for FNDECL. The NRV bitmap
contains the candidates for Named Return Value and OTHER is a list of
- the other return values. */
+ the other return values. GNAT_RET is a representative return node. */
static void
-finalize_nrv (tree fndecl, bitmap nrv, VEC(tree,gc) *other)
+finalize_nrv (tree fndecl, bitmap nrv, VEC(tree,gc) *other, Node_Id gnat_ret)
{
struct cgraph_node *node;
struct nrv_data data;
+ walk_tree_fn func;
unsigned int i;
tree iter;
@@ -2860,8 +3018,13 @@ finalize_nrv (tree fndecl, bitmap nrv, VEC(tree,gc) *other)
/* Adjust the relevant RETURN_EXPRs and replace the occurrences of NRVs. */
data.nrv = nrv;
data.result = DECL_RESULT (fndecl);
+ data.gnat_ret = gnat_ret;
data.visited = pointer_set_create ();
- walk_tree (&DECL_SAVED_TREE (fndecl), finalize_nrv_r, &data, NULL);
+ if (TYPE_RETURN_UNCONSTRAINED_P (TREE_TYPE (fndecl)))
+ func = finalize_nrv_unc_r;
+ else
+ func = finalize_nrv_r;
+ walk_tree (&DECL_SAVED_TREE (fndecl), func, &data, NULL);
pointer_set_destroy (data.visited);
}
@@ -2886,7 +3049,7 @@ return_value_ok_for_nrv_p (tree ret_obj, tree ret_val)
if (TREE_ADDRESSABLE (ret_val))
return false;
- if (DECL_ALIGN (ret_val) > DECL_ALIGN (ret_obj))
+ if (ret_obj && DECL_ALIGN (ret_val) > DECL_ALIGN (ret_obj))
return false;
return true;
@@ -3278,6 +3441,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
save_gnu_tree (gnat_param, NULL_TREE, false);
}
+ /* Disconnect the variable created for the return value. */
if (gnu_return_var_elmt)
TREE_VALUE (gnu_return_var_elmt) = void_type_node;
@@ -3285,8 +3449,10 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
a Named Return Value, finalize the optimization. */
if (optimize && gnu_subprog_language->named_ret_val)
{
- finalize_nrv (gnu_subprog_decl, gnu_subprog_language->named_ret_val,
- gnu_subprog_language->other_ret_val);
+ finalize_nrv (gnu_subprog_decl,
+ gnu_subprog_language->named_ret_val,
+ gnu_subprog_language->other_ret_val,
+ gnu_subprog_language->gnat_ret);
gnu_subprog_language->named_ret_val = NULL;
gnu_subprog_language->other_ret_val = NULL;
}
@@ -5881,6 +6047,34 @@ gnat_to_gnu (Node_Id gnat_node)
else if (TYPE_RETURN_UNCONSTRAINED_P (gnu_subprog_type))
{
gnu_ret_val = maybe_unconstrained_array (gnu_ret_val);
+
+ /* And find out whether this is a candidate for Named Return
+ Value. If so, record it. */
+ if (!TYPE_CI_CO_LIST (gnu_subprog_type) && optimize)
+ {
+ tree ret_val = gnu_ret_val;
+
+ /* Strip useless conversions around the return value. */
+ if (gnat_useless_type_conversion (ret_val))
+ ret_val = TREE_OPERAND (ret_val, 0);
+
+ /* Strip unpadding around the return value. */
+ if (TREE_CODE (ret_val) == COMPONENT_REF
+ && TYPE_IS_PADDING_P
+ (TREE_TYPE (TREE_OPERAND (ret_val, 0))))
+ ret_val = TREE_OPERAND (ret_val, 0);
+
+ /* Now apply the test to the return value. */
+ if (return_value_ok_for_nrv_p (NULL_TREE, ret_val))
+ {
+ if (!f_named_ret_val)
+ f_named_ret_val = BITMAP_GGC_ALLOC ();
+ bitmap_set_bit (f_named_ret_val, DECL_UID (ret_val));
+ if (!f_gnat_ret)
+ f_gnat_ret = gnat_node;
+ }
+ }
+
gnu_ret_val = build_allocator (TREE_TYPE (gnu_ret_val),
gnu_ret_val,
TREE_TYPE (gnu_ret_obj),
@@ -5889,12 +6083,12 @@ gnat_to_gnu (Node_Id gnat_node)
gnat_node, false);
}
- /* If the function returns by invisible reference, dereference
+ /* Otherwise, if it returns by invisible reference, dereference
the pointer it is passed using the type of the return value
and build the copy operation manually. This ensures that we
don't copy too much data, for example if the return type is
unconstrained with a maximum size. */
- if (TREE_ADDRESSABLE (gnu_subprog_type))
+ else if (TREE_ADDRESSABLE (gnu_subprog_type))
{
tree gnu_ret_deref
= build_unary_op (INDIRECT_REF, TREE_TYPE (gnu_ret_val),
@@ -5905,11 +6099,9 @@ gnat_to_gnu (Node_Id gnat_node)
gnu_ret_val = NULL_TREE;
}
}
+
else
- {
- gnu_ret_obj = NULL_TREE;
- gnu_ret_val = NULL_TREE;
- }
+ gnu_ret_obj = gnu_ret_val = NULL_TREE;
/* If we have a return label defined, convert this into a branch to
that label. The return proper will be handled elsewhere. */
@@ -5934,8 +6126,8 @@ gnat_to_gnu (Node_Id gnat_node)
break;
case N_Goto_Statement:
- gnu_result = build1 (GOTO_EXPR, void_type_node,
- gnat_to_gnu (Name (gnat_node)));
+ gnu_result
+ = build1 (GOTO_EXPR, void_type_node, gnat_to_gnu (Name (gnat_node)));
break;
/***************************/
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 73657528a8a..a71a3d28878 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -4744,19 +4744,17 @@ unchecked_convert (tree type, tree expr, bool notrunc_p)
enum tree_code
tree_code_for_record_type (Entity_Id gnat_type)
{
- Node_Id component_list
- = Component_List (Type_Definition
- (Declaration_Node
- (Implementation_Base_Type (gnat_type))));
- Node_Id component;
-
- /* Make this a UNION_TYPE unless it's either not an Unchecked_Union or
- we have a non-discriminant field outside a variant. In either case,
- it's a RECORD_TYPE. */
+ Node_Id component_list, component;
+ /* Return UNION_TYPE if it's an Unchecked_Union whose non-discriminant
+ fields are all in the variant part. Otherwise, return RECORD_TYPE. */
if (!Is_Unchecked_Union (gnat_type))
return RECORD_TYPE;
+ gnat_type = Implementation_Base_Type (gnat_type);
+ component_list
+ = Component_List (Type_Definition (Declaration_Node (gnat_type)));
+
for (component = First_Non_Pragma (Component_Items (component_list));
Present (component);
component = Next_Non_Pragma (component))
diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
index c303e2f20a3..f9e48b79fe5 100644
--- a/gcc/ada/gcc-interface/utils2.c
+++ b/gcc/ada/gcc-interface/utils2.c
@@ -2126,7 +2126,7 @@ maybe_wrap_malloc (tree data_size, tree data_type, Node_Id gnat_node)
return
build2 (COMPOUND_EXPR, TREE_TYPE (aligning_field_addr),
- build_binary_op (MODIFY_EXPR, NULL_TREE,
+ build_binary_op (INIT_EXPR, NULL_TREE,
storage_ptr_slot, storage_ptr),
aligning_field_addr);
}
@@ -2279,12 +2279,12 @@ build_allocator (tree type, tree init, tree result_type, Entity_Id gnat_proc,
CONSTRUCTOR_APPEND_ELT (v, DECL_CHAIN (TYPE_FIELDS (storage_type)),
init);
storage_init
- = build_binary_op (MODIFY_EXPR, NULL_TREE, storage_deref,
+ = build_binary_op (INIT_EXPR, NULL_TREE, storage_deref,
gnat_build_constructor (storage_type, v));
}
else
storage_init
- = build_binary_op (MODIFY_EXPR, NULL_TREE,
+ = build_binary_op (INIT_EXPR, NULL_TREE,
build_component_ref (storage_deref, NULL_TREE,
TYPE_FIELDS (storage_type),
false),
@@ -2332,7 +2332,7 @@ build_allocator (tree type, tree init, tree result_type, Entity_Id gnat_proc,
storage_deref = build_unary_op (INDIRECT_REF, NULL_TREE, storage);
TREE_THIS_NOTRAP (storage_deref) = 1;
storage_init
- = build_binary_op (MODIFY_EXPR, NULL_TREE, storage_deref, init);
+ = build_binary_op (INIT_EXPR, NULL_TREE, storage_deref, init);
return build2 (COMPOUND_EXPR, result_type, storage_init, storage);
}
diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi
index 2d342c347bc..8a51161a8fa 100644
--- a/gcc/ada/gnat_rm.texi
+++ b/gcc/ada/gnat_rm.texi
@@ -374,6 +374,7 @@ The GNAT Library
* GNAT.Exception_Traces (g-exctra.ads)::
* GNAT.Exceptions (g-except.ads)::
* GNAT.Expect (g-expect.ads)::
+* GNAT.Expect.TTY (g-exptty.ads)::
* GNAT.Float_Control (g-flocon.ads)::
* GNAT.Heap_Sort (g-heasor.ads)::
* GNAT.Heap_Sort_A (g-hesora.ads)::
@@ -6372,12 +6373,11 @@ refer to the value of the prefix on entry. So for
example if you have an argument of a record type X called Arg1,
you can refer to Arg1.Field'Old which yields the value of
Arg1.Field on entry. The implementation simply involves generating
-an object declaration which captures the value on entry. Any
-prefix is allowed except one of a limited type (since limited
-types cannot be copied to capture their values) or an expression
-which references a local variable
-(since local variables do not exist at subprogram entry time).
-
+an object declaration which captures the value on entry.
+The prefix must denote an object of a nonlimited type (since limited types
+cannot be copied to capture their values) and it must not reference a local
+variable (since local variables do not exist at subprogram entry time). Note
+that the variable introduced by a quantified expression is a local variable.
The following example shows the use of 'Old to implement
a test of a postcondition:
@@ -9633,7 +9633,8 @@ separate section on Intrinsic Subprograms.
@item Stdcall
Stdcall (used for Windows implementations only). This convention correspond
to the WINAPI (previously called Pascal convention) C/C++ convention under
-Windows. A function with this convention cleans the stack before exit.
+Windows. A routine with this convention cleans the stack before
+exit. This pragma cannot be applied to a dispatching call.
@item DLL
Synonym for Stdcall
@item Win32
@@ -14187,6 +14188,7 @@ of GNAT, and will generate a warning message.
* GNAT.Exception_Traces (g-exctra.ads)::
* GNAT.Exceptions (g-except.ads)::
* GNAT.Expect (g-expect.ads)::
+* GNAT.Expect.TTY (g-exptty.ads)::
* GNAT.Float_Control (g-flocon.ads)::
* GNAT.Heap_Sort (g-heasor.ads)::
* GNAT.Heap_Sort_A (g-hesora.ads)::
@@ -15054,6 +15056,16 @@ is implemented on all native GNAT ports except for OpenVMS@.
It is not implemented for cross ports, and in particular is not
implemented for VxWorks or LynxOS@.
+@node GNAT.Expect.TTY (g-exptty.ads)
+@section @code{GNAT.Expect.TTY} (@file{g-exptty.ads})
+@cindex @code{GNAT.Expect.TTY} (@file{g-exptty.ads})
+
+@noindent
+As GNAT.Expect but using pseudo-terminal.
+Currently @code{GNAT.Expect.TTY} is implemented on all native GNAT
+ports except for OpenVMS@. It is not implemented for cross ports, and
+in particular is not implemented for VxWorks or LynxOS@.
+
@node GNAT.Float_Control (g-flocon.ads)
@section @code{GNAT.Float_Control} (@file{g-flocon.ads})
@cindex @code{GNAT.Float_Control} (@file{g-flocon.ads})
diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi
index 253cfff172b..ba5737a487e 100644
--- a/gcc/ada/gnat_ugn.texi
+++ b/gcc/ada/gnat_ugn.texi
@@ -11805,7 +11805,7 @@ recognized by GNAT:
@section Handling of Configuration Pragmas
Configuration pragmas may either appear at the start of a compilation
-unit, in which case they apply only to that unit, or they may apply to
+unit, or they can appear in a configuration pragma file to apply to
all compilations performed in a given compilation environment.
GNAT also provides the @code{gnatchop} utility to provide an automatic
@@ -11816,6 +11816,30 @@ However, for most purposes, it will be more convenient to edit the
@file{gnat.adc} file that contains configuration pragmas directly,
as described in the following section.
+In the case of @code{Restrictions} pragmas appearing as configuration
+pragmas in individual compilation units, the exact handling depends on
+the type of restriction.
+
+Restrictions that require partition-wide consistency (like
+@code{No_Tasking}) are
+recognized wherever they appear
+and can be freely inherited, e.g. from a with'ed unit to the with'ing
+unit. This makes sense since the binder will in any case insist on seeing
+consistent use, so any unit not conforming to any restrictions that are
+anywhere in the partition will be rejected, and you might as well find
+that out at compile time rather than at bind time.
+
+For restrictions that do not require partition-wide consistency, e.g.
+SPARK or No_Implementation_Attributes, in general the restriction applies
+only to the unit in which the pragma appears, and not to any other units.
+
+The exception is No_Elaboration_Code which always applies to the entire
+object file from a compilation, i.e. to the body, spec, and all subunits.
+This restriction can be specified in a configuration pragma file, or it
+can be on the body and/or the spec (in eithe case it applies to all the
+relevant units). It can appear on a subunit only if it has previously
+appeared in the body of spec.
+
@node The Configuration Pragmas Files
@section The Configuration Pragmas Files
@cindex @file{gnat.adc}
@@ -13164,6 +13188,23 @@ setting.
Enumeration literals are in mixed case. Overrides ^-n^/NAME_CASING^ casing
setting.
+@cindex @option{^-nt@var{x}^/TYPE_CASING^} (@command{gnatpp})
+@item ^-neD^/TYPE_CASING=AS_DECLARED^
+Type and subtype name casing for defining occurrences are as they appear in
+the source file. Overrides ^-n^/NAME_CASING^ casing setting.
+
+@item ^-ntU^/TYPE_CASING=UPPER_CASE^
+Type and subtype names are in upper case. Overrides ^-n^/NAME_CASING^ casing
+setting.
+
+@item ^-ntL^/TYPE_CASING=LOWER_CASE^
+Type and subtype names are in lower case. Overrides ^-n^/NAME_CASING^ casing
+setting.
+
+@item ^-ntM^/TYPE_CASING=MIXED_CASE^
+Type and subtype names 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
@@ -13364,6 +13405,19 @@ and variants if there are @var{nnn} or more (the default
value is 10).
If @var{nnn} is 0, an additional indentation level is
used for @b{case} alternatives and variants regardless of their number.
+
+@item ^--call_threshold=@var{nnn}^/MAX_ACT=@var{nnn}^
+@cindex @option{^--call_threshold^/MAX_ACT^} (@command{gnatpp})
+If the number of parameter associations is greater than @var{nnn} and if at
+least one association uses named notation, start each association from
+a new line. If @var{nnn} is 0, no check for the number of associations
+is made, this is the default.
+
+@item ^--par_threshold=@var{nnn}^/MAX_PAR=@var{nnn}^
+@cindex @option{^--par_threshold^/MAX_PAR^} (@command{gnatpp})
+If the number of parameter specifications is greater than @var{nnn}
+(or equal to @var{nnn} in case of a function), start each specification from
+a new line. The default for @var{nnn} is 3.
@end table
@node Setting the Source Search Path
@@ -17889,6 +17943,9 @@ gnatmake -P<harness-dir>/test_driver
test_runner
@end smallexample
+Note that you might need to specify the necessary values of scenario variables
+when you are not using the AUnit defaults.
+
@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
@@ -17899,6 +17956,9 @@ 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 a signature encoding used to
differentiate test names in cases of overloading.
+
+Note that if the project already has both my_unit.ads and my_unit-tests.ads this
+will cause name a conflict with generated test package.
@end itemize
@node Switches for gnattest
@@ -17921,6 +17981,10 @@ manual tests to be added to the test suite.
@cindex @option{-r} (@command{gnattest})
Recursively consider all sources from all projects.
+@item -X@var{name=value}
+@cindex @option{-X} (@command{gnattest})
+Indicate that external variable @var{name} has the value @var{value}.
+
@item -q
@cindex @option{-q} (@command{gnattest})
Suppresses noncritical output messages.
@@ -18311,6 +18375,8 @@ The tool currently does not support following features:
@item generic tests for generic packages and package instantiations
@item tests for protected subprograms and entries
@item aspects Precondition, Postcondition, and Test_Case
+@item generating test packages for code that is not conformant with ada 2005
+
@end itemize
@c *********************************
diff --git a/gcc/ada/impunit.adb b/gcc/ada/impunit.adb
index 63ab9256953..496f6ce50d4 100644
--- a/gcc/ada/impunit.adb
+++ b/gcc/ada/impunit.adb
@@ -270,6 +270,7 @@ package body Impunit is
("g-except", F), -- GNAT.Exceptions
("g-exctra", F), -- GNAT.Exception_Traces
("g-expect", F), -- GNAT.Expect
+ ("g-exptty", F), -- GNAT.Expect.TTY
("g-flocon", F), -- GNAT.Float_Control
("g-heasor", F), -- GNAT.Heap_Sort
("g-hesora", F), -- GNAT.Heap_Sort_A
@@ -318,6 +319,7 @@ package body Impunit is
("g-timsta", F), -- GNAT.Time_Stamp
("g-traceb", F), -- GNAT.Traceback
("g-trasym", F), -- GNAT.Traceback.Symbolic
+ ("g-tty ", F), -- GNAT.TTY
("g-utf_32", F), -- GNAT.UTF_32
("g-u3spch", F), -- GNAT.UTF_32_Spelling_Checker
("g-wispch", F), -- GNAT.Wide_Spelling_Checker
diff --git a/gcc/ada/init.c b/gcc/ada/init.c
index 8d2f4e1f235..cc6c1d2c50b 100644
--- a/gcc/ada/init.c
+++ b/gcc/ada/init.c
@@ -1808,8 +1808,8 @@ __gnat_error_handler (int sig,
break;
case SIGBUS:
- exception = &constraint_error;
- msg = "SIGBUS";
+ exception = &storage_error;
+ msg = "SIGBUS: possible stack overflow";
break;
default:
@@ -2282,11 +2282,12 @@ __gnat_is_stack_guard (mach_vm_address_t addr)
return 0;
}
-static void
-__gnat_error_handler (int sig, siginfo_t *si, void *ucontext ATTRIBUTE_UNUSED)
+#define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
+
+void
+__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
+ 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
@@ -2294,9 +2295,19 @@ __gnat_error_handler (int sig, siginfo_t *si, void *ucontext ATTRIBUTE_UNUSED)
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
+}
+
+static void
+__gnat_error_handler (int sig, siginfo_t *si, void *ucontext)
+{
+ struct Exception_Data *exception;
+ const char *msg;
+
+ __gnat_adjust_context_for_raise (sig, ucontext);
switch (sig)
{
diff --git a/gcc/ada/layout.adb b/gcc/ada/layout.adb
index bb8aa113211..519fad0f357 100644
--- a/gcc/ada/layout.adb
+++ b/gcc/ada/layout.adb
@@ -3088,7 +3088,7 @@ package body Layout is
end if;
-- Here we calculate the alignment as the largest power of two multiple
- -- of System.Storage_Unit that does not exceed either the actual size of
+ -- of System.Storage_Unit that does not exceed either the object size of
-- the type, or the maximum allowed alignment.
declare
@@ -3126,21 +3126,101 @@ package body Layout is
A := 2 * A;
end loop;
- -- Now we think we should set the alignment to A, but we skip this if
- -- an alignment is already set to a value greater than A (happens for
- -- derived types).
+ -- If alignment is currently not set, then we can safetly set it to
+ -- this new calculated value.
- -- However, if the alignment is known and too small it must be
- -- increased, this happens in a case like:
+ if Unknown_Alignment (E) then
+ Init_Alignment (E, A);
+
+ -- Cases where we have inherited an alignment
+
+ -- For constructed types, always reset the alignment, these are
+ -- Generally invisible to the user anyway, and that way we are
+ -- sure that no constructed types have weird alignments.
+
+ elsif not Comes_From_Source (E) then
+ Init_Alignment (E, A);
+
+ -- If this inherited alignment is the same as the one we computed,
+ -- then obviously everything is fine, and we do not need to reset it.
- -- type R is new Character;
- -- for R'Size use 16;
+ elsif Alignment (E) = A then
+ null;
- -- Here the alignment inherited from Character is 1, but it must be
- -- increased to 2 to reflect the increased size.
+ -- Now we come to the difficult cases where we have inherited an
+ -- alignment and size, but overridden the size but not the alignment.
+
+ elsif Has_Size_Clause (E) or else Has_Object_Size_Clause (E) then
+
+ -- This is tricky, it might be thought that we should try to
+ -- inherit the alignment, since that's what the RM implies, but
+ -- that leads to complex rules and oddities. Consider for example:
+
+ -- type R is new Character;
+ -- for R'Size use 16;
+
+ -- It seems quite bogus in this case to inherit an alignment of 1
+ -- from the parent type Character. Furthermore, if that's what the
+ -- programmer really wanted for some odd reason, then they could
+ -- specify the alignment they wanted.
+
+ -- Furthermore we really don't want to inherit the alignment in
+ -- the case of a specified Object_Size for a subtype, since then
+ -- there would be no way of overriding to give a reasonable value
+ -- (we don't have an Object_Subtype attribute). Consider:
+
+ -- subtype R is new Character;
+ -- for R'Object_Size use 16;
+
+ -- If we inherit the alignment of 1, then we have an odd
+ -- inefficient alignment for the subtype, which cannot be fixed.
+
+ -- So we make the decision that if Size (or Object_Size) is given
+ -- (and, in the case of a first subtype, the alignment is not set
+ -- with a specific alignment clause). We reset the alignment to
+ -- the appropriate value for the specified size. This is a nice
+ -- simple rule to implement and document.
+
+ -- There is one slight glitch, which is that a confirming size
+ -- clause can now change the alignment, which, if we really think
+ -- that confirming rep clauses should have no effect, is a no-no.
+
+ -- type R is new Character;
+ -- for R'Alignment use 2;
+ -- type S is new R;
+ -- for S'Size use Character'Size;
+
+ -- Now the alignment of S is 1 instead of 2, as a result of
+ -- applying the above rule to the confirming rep clause for S. Not
+ -- clear this is worth worrying about. If we recorded whether a
+ -- size clause was confirming we could avoid this, but right now
+ -- we have no way of doing that or easily figuring it out, so we
+ -- don't bother.
+
+ -- Historical note. In versions of GNAT prior to Nov 6th, 2010, an
+ -- odd distinction was made between inherited alignments greater
+ -- than the computed alignment (where the larger alignment was
+ -- inherited) and inherited alignments smaller than the computed
+ -- alignment (where the smaller alignment was overridden). This
+ -- was a dubious fix to get around an ACATS problem which seems
+ -- to have disappeared anyway, and in any case, this peculiarity
+ -- was never documented.
- if Unknown_Alignment (E) or else Alignment (E) < A then
Init_Alignment (E, A);
+
+ -- If no Size (or Object_Size) was specified, then we inherited the
+ -- object size, so we should inherit the alignment as well and not
+ -- modify it. This takes care of cases like:
+
+ -- type R is new Integer;
+ -- for R'Alignment use 1;
+ -- subtype S is R;
+
+ -- Here we have R has a default Object_Size of 32, and a specified
+ -- alignment of 1, and it seeems right for S to inherit both values.
+
+ else
+ null;
end if;
end;
end Set_Elem_Alignment;
diff --git a/gcc/ada/lib-load.adb b/gcc/ada/lib-load.adb
index 894c76017d9..0ac729ece6c 100644
--- a/gcc/ada/lib-load.adb
+++ b/gcc/ada/lib-load.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- --
@@ -359,9 +359,25 @@ package body Lib.Load is
Src_Ind : Source_File_Index;
Save_PMES : constant Boolean := Parsing_Main_Extended_Source;
+ Save_Cunit_Restrictions : constant Save_Cunit_Boolean_Restrictions :=
+ Cunit_Boolean_Restrictions_Save;
+ -- Save current restrictions for restore at end
+
begin
Parsing_Main_Extended_Source := PMES;
+ -- Initialize restrictions to config restrictions for unit to load if
+ -- it is part of the main extended source, otherwise reset them.
+
+ -- Note: it's a bit odd but PMES is False for subunits, which is why
+ -- we have the OR here. Should be investigated some time???
+
+ if PMES or Subunit then
+ Restore_Config_Cunit_Boolean_Restrictions;
+ else
+ Reset_Cunit_Boolean_Restrictions;
+ end if;
+
-- If renamings are allowed and we have a child unit name, then we
-- must first load the parent to deal with finding the real name.
-- Retain the with_clause that names the child, so that if it is
@@ -782,6 +798,7 @@ package body Lib.Load is
<<Done>>
Parsing_Main_Extended_Source := Save_PMES;
+ Cunit_Boolean_Restrictions_Restore (Save_Cunit_Restrictions);
return Unum;
end Load_Unit;
diff --git a/gcc/ada/lib-load.ads b/gcc/ada/lib-load.ads
index d2856aa41f2..a029d3793b0 100644
--- a/gcc/ada/lib-load.ads
+++ b/gcc/ada/lib-load.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- --
@@ -155,6 +155,7 @@ package Lib.Load is
--
-- PMES indicates the required setting of Parsing_Main_Extended_Unit during
-- loading of the unit. This flag is saved and restored over the call.
+ -- Note: PMES is false for the subunit case, which seems wrong???
procedure Change_Main_Unit_To_Spec;
-- This procedure is called if the main unit file contains a No_Body pragma
diff --git a/gcc/ada/lib-xref.adb b/gcc/ada/lib-xref.adb
index 83a06e452f3..0e8337f70c6 100644
--- a/gcc/ada/lib-xref.adb
+++ b/gcc/ada/lib-xref.adb
@@ -577,14 +577,16 @@ package body Lib.Xref is
-- doing in such cases. For example the calls in Ada.Characters.Handling
-- to its own obsolescent subprograms are just fine.
- -- In any case we do not generate warnings within the extended source
- -- unit of the entity in question, since we assume the source unit
- -- itself knows what is going on (and for sure we do not want silly
- -- warnings, e.g. on the end line of an obsolescent procedure body).
+ -- In any case we only generate warnings if we are in the extended main
+ -- source unit, and the entity itself is not in the extended main source
+ -- unit, since we assume the source unit itself knows what is going on
+ -- (and for sure we do not want silly warnings, e.g. on the end line of
+ -- an obsolescent procedure body).
if Is_Obsolescent (E)
and then not GNAT_Mode
and then not In_Extended_Main_Source_Unit (E)
+ and then In_Extended_Main_Source_Unit (N)
then
Check_Restriction (No_Obsolescent_Features, N);
diff --git a/gcc/ada/lib.ads b/gcc/ada/lib.ads
index 76810c22862..2b3f90650cd 100644
--- a/gcc/ada/lib.ads
+++ b/gcc/ada/lib.ads
@@ -518,7 +518,7 @@ package Lib is
-- its subunits (considered recursively). Units for which this enquiry
-- returns True are those for which code will be generated. Nodes from
-- instantiations are included in the extended main unit for this call.
- -- If the main unit is itself a subunit, then the extended main unit
+ -- If the main unit is itself a subunit, then the extended main code unit
-- includes its parent unit, and the parent unit spec if it is separate.
function In_Extended_Main_Code_Unit (Loc : Source_Ptr) return Boolean;
@@ -533,7 +533,7 @@ package Lib is
-- returns True are those for which code will be generated. This differs
-- from In_Extended_Main_Code_Unit only in that instantiations are not
-- included for the purposes of this call. If the main unit is itself
- -- a subunit, then the extended main unit includes its parent unit,
+ -- a subunit, then the extended main source unit includes its parent unit,
-- and the parent unit spec if it is separate.
function In_Extended_Main_Source_Unit (Loc : Source_Ptr) return Boolean;
diff --git a/gcc/ada/mlib-tgt-specific-darwin.adb b/gcc/ada/mlib-tgt-specific-darwin.adb
index e04225370eb..13beb04a8bf 100644
--- a/gcc/ada/mlib-tgt-specific-darwin.adb
+++ b/gcc/ada/mlib-tgt-specific-darwin.adb
@@ -36,8 +36,6 @@ package body MLib.Tgt.Specific is
-- Non default subprograms
- function Archive_Indexer_Options return String_List_Access;
-
procedure Build_Dynamic_Library
(Ofiles : Argument_List;
Options : Argument_List;
@@ -62,15 +60,6 @@ package body MLib.Tgt.Specific is
Shared_Options : constant Argument_List :=
(1 => Shared_Libgcc'Access);
- -----------------------------
- -- Archive_Indexer_Options --
- -----------------------------
-
- function Archive_Indexer_Options return String_List_Access is
- begin
- return new String_List'(1 => new String'("-c"));
- end Archive_Indexer_Options;
-
---------------------------
-- Build_Dynamic_Library --
---------------------------
@@ -175,7 +164,6 @@ package body MLib.Tgt.Specific is
end Is_Archive_Ext;
begin
- Archive_Indexer_Options_Ptr := Archive_Indexer_Options'Access;
Build_Dynamic_Library_Ptr := Build_Dynamic_Library'Access;
DLL_Ext_Ptr := DLL_Ext'Access;
Dynamic_Option_Ptr := Dynamic_Option'Access;
diff --git a/gcc/ada/mlib-tgt-specific-vxworks.adb b/gcc/ada/mlib-tgt-specific-vxworks.adb
index 1e1fad1d777..17a9d74a17f 100644
--- a/gcc/ada/mlib-tgt-specific-vxworks.adb
+++ b/gcc/ada/mlib-tgt-specific-vxworks.adb
@@ -7,7 +7,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2003-2008, Free Software Foundation, Inc. --
+-- Copyright (C) 2003-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- --
@@ -132,9 +132,9 @@ package body MLib.Tgt.Specific is
return "";
end Dynamic_Option;
- -----------------------------
+ -----------------------
-- Get_Target_Suffix --
- -----------------------------
+ -----------------------
function Get_Target_Suffix return String is
Target_Name : constant String := Sdefault.Target_Name.all;
diff --git a/gcc/ada/opt.ads b/gcc/ada/opt.ads
index e6a42815e82..4c1f5609318 100644
--- a/gcc/ada/opt.ads
+++ b/gcc/ada/opt.ads
@@ -140,7 +140,7 @@ package Opt is
-- or internal units, so it reflects the Ada version explicitly set
-- using configuration pragmas or compiler switches (or if neither
-- appears, it remains set to Ada_Version_Default). This is used in
- -- the rare cases (notably for pragmas Preelaborate_05 and Pure_05)
+ -- the rare cases (notably for pragmas Preelaborate_05 and Pure_05/12)
-- where in the run-time we want the explicit version set.
Ada_Version_Runtime : Ada_Version_Type := Ada_2012;
@@ -1830,6 +1830,9 @@ package Opt is
-- this flag, see package Expander. Indeed this flag might more logically
-- be in the spec of Expander, but it is referenced by Errout, and it
-- really seems wrong for Errout to depend on Expander.
+ --
+ -- Note: for many purposes, it is more appropriate to test the flag
+ -- Full_Expander_Active, which also checks that Alfa mode is not active.
Static_Dispatch_Tables : Boolean := True;
-- This flag indicates if the backend supports generation of statically
diff --git a/gcc/ada/par-ch4.adb b/gcc/ada/par-ch4.adb
index 85b4024df8c..59884d24c73 100644
--- a/gcc/ada/par-ch4.adb
+++ b/gcc/ada/par-ch4.adb
@@ -2553,6 +2553,11 @@ package body Ch4 is
Node1 : Node_Id;
begin
+ if Ada_Version < Ada_2012 then
+ Error_Msg_SC ("quantified expression is an Ada 2012 feature");
+ Error_Msg_SC ("\|unit must be compiled with -gnat2012 switch");
+ end if;
+
Scan; -- past FOR
Node1 := New_Node (N_Quantified_Expression, Prev_Token_Ptr);
diff --git a/gcc/ada/par-ch6.adb b/gcc/ada/par-ch6.adb
index 7d598547911..36691f34d28 100644
--- a/gcc/ada/par-ch6.adb
+++ b/gcc/ada/par-ch6.adb
@@ -108,7 +108,8 @@ package body Ch6 is
-- end [DESIGNATOR];
-- SUBPROGRAM_RENAMING_DECLARATION ::=
- -- SUBPROGRAM_SPECIFICATION renames callable_entity_NAME;
+ -- SUBPROGRAM_SPECIFICATION renames callable_entity_NAME
+ -- [ASPECT_SPECIFICATIONS];
-- SUBPROGRAM_BODY_STUB ::=
-- SUBPROGRAM_SPECIFICATION is separate;
@@ -506,6 +507,7 @@ package body Ch6 is
Scan; -- past RENAMES
Set_Name (Rename_Node, P_Name);
Set_Specification (Rename_Node, Specification_Node);
+ P_Aspect_Specifications (Rename_Node);
TF_Semicolon;
Pop_Scope_Stack;
return Rename_Node;
@@ -1679,7 +1681,7 @@ package body Ch6 is
if Ada_Version < Ada_2012 then
Error_Msg_SC -- CODEFIX
- ("ALIASED not allowed in extended return in Ada2012?");
+ ("ALIASED not allowed in extended return in Ada 2012?");
else
Error_Msg_SC -- CODEFIX
("ALIASED not allowed in extended return");
diff --git a/gcc/ada/par-prag.adb b/gcc/ada/par-prag.adb
index 224b992274e..1a126759f6b 100644
--- a/gcc/ada/par-prag.adb
+++ b/gcc/ada/par-prag.adb
@@ -1216,6 +1216,7 @@ begin
Pragma_Psect_Object |
Pragma_Pure |
Pragma_Pure_05 |
+ Pragma_Pure_12 |
Pragma_Pure_Function |
Pragma_Queuing_Policy |
Pragma_Relative_Deadline |
diff --git a/gcc/ada/par-util.adb b/gcc/ada/par-util.adb
index 259cfb8e789..f281c7964f0 100644
--- a/gcc/ada/par-util.adb
+++ b/gcc/ada/par-util.adb
@@ -174,7 +174,7 @@ package body Util is
procedure Check_Future_Keyword is
begin
- -- Ada 2005 (AI-284): Compiling in Ada95 mode we warn that INTERFACE,
+ -- Ada 2005 (AI-284): Compiling in Ada 95 mode we warn that INTERFACE,
-- OVERRIDING, and SYNCHRONIZED are new reserved words.
if Ada_Version = Ada_95
diff --git a/gcc/ada/prj-part.adb b/gcc/ada/prj-part.adb
index 022efe3c80b..23ad841a3c5 100644
--- a/gcc/ada/prj-part.adb
+++ b/gcc/ada/prj-part.adb
@@ -99,12 +99,15 @@ package body Prj.Part is
package Virtual_Hash is new GNAT.HTable.Simple_HTable
(Header_Num => Header_Num,
Element => Project_Node_Id,
- No_Element => Empty_Node,
+ No_Element => Project_Node_High_Bound,
Key => Project_Node_Id,
Hash => Prj.Tree.Hash,
Equal => "=");
- -- Hash table to store the node id of the project for which a virtual
- -- extending project need to be created.
+ -- Hash table to store the node ids of projects for which a virtual
+ -- extending project need to be created. The corresponding value is the
+ -- head of a list of WITH clauses corresponding to the context of the
+ -- enclosing EXTEND ALL projects. Note: Default_Element is Project_Node_
+ -- High_Bound because we want Empty_Node to be a possible value.
package Processed_Hash is new GNAT.HTable.Simple_HTable
(Header_Num => Header_Num,
@@ -148,11 +151,13 @@ package body Prj.Part is
-- Check that an aggregate project only imports abstract projects
procedure Create_Virtual_Extending_Project
- (For_Project : Project_Node_Id;
- Main_Project : Project_Node_Id;
- In_Tree : Project_Node_Tree_Ref);
+ (For_Project : Project_Node_Id;
+ Main_Project : Project_Node_Id;
+ Extension_Withs : Project_Node_Id;
+ In_Tree : Project_Node_Tree_Ref);
-- Create a virtual extending project of For_Project. Main_Project is
- -- the extending all project.
+ -- the extending all project. Extension_Withs is the head of a WITH clause
+ -- list to be added to the created virtual project.
--
-- The String_Value_Of is not set for the automatically added with
-- clause and keeps the default value of No_Name. This enables Prj.PP
@@ -236,14 +241,45 @@ package body Prj.Part is
-- Returns No_Name if the path name is invalid, because the corresponding
-- project name does not have the syntax of an ada identifier.
+ function Copy_With_Clause
+ (With_Clause : Project_Node_Id;
+ In_Tree : Project_Node_Tree_Ref;
+ Next_Clause : Project_Node_Id) return Project_Node_Id;
+ -- Return a copy of With_Clause in In_Tree, whose Next_With_Clause is the
+ -- indicated one.
+
+ ----------------------
+ -- Copy_With_Clause --
+ ----------------------
+
+ function Copy_With_Clause
+ (With_Clause : Project_Node_Id;
+ In_Tree : Project_Node_Tree_Ref;
+ Next_Clause : Project_Node_Id) return Project_Node_Id
+ is
+ New_With_Clause : constant Project_Node_Id :=
+ Default_Project_Node (In_Tree, N_With_Clause);
+ begin
+ Set_Name_Of (New_With_Clause, In_Tree,
+ Name_Of (With_Clause, In_Tree));
+ Set_Path_Name_Of (New_With_Clause, In_Tree,
+ Path_Name_Of (With_Clause, In_Tree));
+ Set_Project_Node_Of (New_With_Clause, In_Tree,
+ Project_Node_Of (With_Clause, In_Tree));
+ Set_Next_With_Clause_Of (New_With_Clause, In_Tree, Next_Clause);
+
+ return New_With_Clause;
+ end Copy_With_Clause;
+
--------------------------------------
-- Create_Virtual_Extending_Project --
--------------------------------------
procedure Create_Virtual_Extending_Project
- (For_Project : Project_Node_Id;
- Main_Project : Project_Node_Id;
- In_Tree : Project_Node_Tree_Ref)
+ (For_Project : Project_Node_Id;
+ Main_Project : Project_Node_Id;
+ Extension_Withs : Project_Node_Id;
+ In_Tree : Project_Node_Tree_Ref)
is
Virtual_Name : constant String :=
@@ -323,7 +359,8 @@ package body Prj.Part is
Project_Declaration := Project_Declaration_Of (Virtual_Project, In_Tree);
- -- With clause
+ -- Add a WITH clause to the main project to import the newly created
+ -- virtual extending project.
Set_Name_Of (With_Clause, In_Tree, Virtual_Name_Id);
Set_Path_Name_Of (With_Clause, In_Tree, Virtual_Path_Id);
@@ -332,6 +369,21 @@ package body Prj.Part is
(With_Clause, In_Tree, First_With_Clause_Of (Main_Project, In_Tree));
Set_First_With_Clause_Of (Main_Project, In_Tree, With_Clause);
+ -- Copy with clauses for projects imported by the extending-all project
+
+ declare
+ Org_With_Clause : Project_Node_Id := Extension_Withs;
+ New_With_Clause : Project_Node_Id := Empty_Node;
+ begin
+ while Present (Org_With_Clause) loop
+ New_With_Clause :=
+ Copy_With_Clause (Org_With_Clause, In_Tree, New_With_Clause);
+
+ Org_With_Clause := Next_With_Clause_Of (Org_With_Clause, In_Tree);
+ end loop;
+ Set_First_With_Clause_Of (Virtual_Project, In_Tree, New_With_Clause);
+ end;
+
-- Virtual project node
Set_Location_Of
@@ -371,6 +423,14 @@ package body Prj.Part is
-- Look_For_Virtual_Projects_For --
-----------------------------------
+ Extension_Withs : Project_Node_Id;
+ -- Head of the current EXTENDS ALL imports list. When creating virtual
+ -- projects for an EXTENDS ALL, we import in each virtual project all
+ -- of the projects that appear in WITH clauses of the extending projects.
+ -- This ensures that virtual projects share a consistent environment (in
+ -- particular if a project imported by one of the extending projects
+ -- replaces some runtime units).
+
procedure Look_For_Virtual_Projects_For
(Proj : Project_Node_Id;
In_Tree : Project_Node_Tree_Ref;
@@ -388,9 +448,13 @@ package body Prj.Part is
Extended : Project_Node_Id := Empty_Node;
-- Node for the eventual project extended by Proj
+ Extends_All : Boolean := False;
+ -- Set True if Proj is an EXTENDS ALL project
+
+ Saved_Extension_Withs : constant Project_Node_Id := Extension_Withs;
+
begin
- -- Nothing to do if Proj is not defined or if it has already been
- -- processed.
+ -- Nothing to do if Proj is undefined or has already been processed
if Present (Proj) and then not Processed_Hash.Get (Proj) then
-- Make sure the project will not be processed again
@@ -401,13 +465,14 @@ package body Prj.Part is
if Present (Declaration) then
Extended := Extended_Project_Of (Declaration, In_Tree);
+ Extends_All := Is_Extending_All (Proj, In_Tree);
end if;
-- If this is a project that may need a virtual extending project
-- and it is not itself an extending project, put it in the list.
if Potentially_Virtual and then No (Extended) then
- Virtual_Hash.Set (Proj, Proj);
+ Virtual_Hash.Set (Proj, Extension_Withs);
end if;
-- Now check the projects it imports
@@ -422,6 +487,14 @@ package body Prj.Part is
(Imported, In_Tree, Potentially_Virtual => True);
end if;
+ if Extends_All then
+ -- This is an EXTENDS ALL project: prepend each of its WITH
+ -- clauses to the currently active list of extension deps.
+
+ Extension_Withs :=
+ Copy_With_Clause (With_Clause, In_Tree, Extension_Withs);
+ end if;
+
With_Clause := Next_With_Clause_Of (With_Clause, In_Tree);
end loop;
@@ -431,6 +504,8 @@ package body Prj.Part is
Look_For_Virtual_Projects_For
(Extended, In_Tree, Potentially_Virtual => False);
+
+ Extension_Withs := Saved_Extension_Withs;
end if;
end Look_For_Virtual_Projects_For;
@@ -550,6 +625,7 @@ package body Prj.Part is
Declaration : constant Project_Node_Id :=
Project_Declaration_Of (Project, In_Tree);
begin
+ Extension_Withs := First_With_Clause_Of (Project, In_Tree);
Look_For_Virtual_Projects_For
(Extended_Project_Of (Declaration, In_Tree), In_Tree,
Potentially_Virtual => False);
@@ -595,11 +671,14 @@ package body Prj.Part is
-- Now create all the virtual extending projects
declare
- Proj : Project_Node_Id := Virtual_Hash.Get_First;
+ Proj : Project_Node_Id := Empty_Node;
+ Withs : Project_Node_Id;
begin
- while Present (Proj) loop
- Create_Virtual_Extending_Project (Proj, Project, In_Tree);
- Proj := Virtual_Hash.Get_Next;
+ Virtual_Hash.Get_First (Proj, Withs);
+ while Withs /= Project_Node_High_Bound loop
+ Create_Virtual_Extending_Project
+ (Proj, Project, Withs, In_Tree);
+ Virtual_Hash.Get_Next (Proj, Withs);
end loop;
end;
end if;
diff --git a/gcc/ada/prj-pp.adb b/gcc/ada/prj-pp.adb
index cf0ae4a6619..6e9e61bc2a6 100644
--- a/gcc/ada/prj-pp.adb
+++ b/gcc/ada/prj-pp.adb
@@ -968,4 +968,15 @@ package body Prj.PP is
Output.Write_Eol;
end Output_Statistics;
+ ---------
+ -- wpr --
+ ---------
+
+ procedure wpr
+ (Project : Prj.Tree.Project_Node_Id;
+ In_Tree : Prj.Tree.Project_Node_Tree_Ref) is
+ begin
+ Pretty_Print (Project, In_Tree, Backward_Compatibility => False);
+ end wpr;
+
end Prj.PP;
diff --git a/gcc/ada/prj-pp.ads b/gcc/ada/prj-pp.ads
index f47e0582b35..771b4c3f2d4 100644
--- a/gcc/ada/prj-pp.ads
+++ b/gcc/ada/prj-pp.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 2001-2010, Free Software Foundation, Inc. --
+-- Copyright (C) 2001-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- --
@@ -91,4 +91,9 @@ private
-- display what Project_Node_Kinds have not been exercised by the call(s)
-- to Pretty_Print. It is used only for testing purposes.
+ procedure wpr
+ (Project : Prj.Tree.Project_Node_Id;
+ In_Tree : Prj.Tree.Project_Node_Tree_Ref);
+ -- Wrapper for use from gdb: call Pretty_Print with default parameters
+
end Prj.PP;
diff --git a/gcc/ada/restrict.adb b/gcc/ada/restrict.adb
index 813568deea6..df2ec7a888c 100644
--- a/gcc/ada/restrict.adb
+++ b/gcc/ada/restrict.adb
@@ -41,6 +41,9 @@ with Uname; use Uname;
package body Restrict is
+ Config_Cunit_Boolean_Restrictions : Save_Cunit_Boolean_Restrictions;
+ -- Save compilation unit restrictions set by config pragma files
+
Restricted_Profile_Result : Boolean := False;
-- This switch memoizes the result of Restricted_Profile function calls for
-- improved efficiency. Valid only if Restricted_Profile_Cached is True.
@@ -100,6 +103,17 @@ package body Restrict is
end if;
end Abort_Allowed;
+ ----------------------------------------
+ -- Add_To_Config_Boolean_Restrictions --
+ ----------------------------------------
+
+ procedure Add_To_Config_Boolean_Restrictions (R : Restriction_Id) is
+ begin
+ Config_Cunit_Boolean_Restrictions (R) := True;
+ end Add_To_Config_Boolean_Restrictions;
+ -- Add specified restriction to stored configuration boolean restrictions.
+ -- This is used for handling the special case of No_Elaboration_Code.
+
-------------------------
-- Check_Compiler_Unit --
-------------------------
@@ -183,6 +197,78 @@ package body Restrict is
end if;
end Check_SPARK_Restriction;
+ --------------------------------
+ -- Check_No_Implicit_Aliasing --
+ --------------------------------
+
+ procedure Check_No_Implicit_Aliasing (Obj : Node_Id) is
+ E : Entity_Id;
+
+ begin
+ -- If restriction not active, nothing to check
+
+ if not Restriction_Active (No_Implicit_Aliasing) then
+ return;
+ end if;
+
+ -- If we have an entity name, check entity
+
+ if Is_Entity_Name (Obj) then
+ E := Entity (Obj);
+
+ -- Restriction applies to entities that are objects
+
+ if Is_Object (E) then
+ if Is_Aliased (E) then
+ return;
+
+ elsif Present (Renamed_Object (E)) then
+ Check_No_Implicit_Aliasing (Renamed_Object (E));
+ return;
+ end if;
+
+ -- If we don't have an object, then it's OK
+
+ else
+ return;
+ end if;
+
+ -- For selected component, check selector
+
+ elsif Nkind (Obj) = N_Selected_Component then
+ Check_No_Implicit_Aliasing (Selector_Name (Obj));
+ return;
+
+ -- Indexed component is OK if aliased components
+
+ elsif Nkind (Obj) = N_Indexed_Component then
+ if Has_Aliased_Components (Etype (Prefix (Obj)))
+ or else
+ (Is_Access_Type (Etype (Prefix (Obj)))
+ and then Has_Aliased_Components
+ (Designated_Type (Etype (Prefix (Obj)))))
+ then
+ return;
+ end if;
+
+ -- For type conversion, check converted expression
+
+ elsif Nkind_In (Obj, N_Unchecked_Type_Conversion, N_Type_Conversion) then
+ Check_No_Implicit_Aliasing (Expression (Obj));
+ return;
+
+ -- Explicit dereference is always OK
+
+ elsif Nkind (Obj) = N_Explicit_Dereference then
+ return;
+ end if;
+
+ -- If we fall through, then we have an aliased view that does not meet
+ -- the rules for being explicitly aliased, so issue restriction msg.
+
+ Check_Restriction (No_Implicit_Aliasing, Obj);
+ end Check_No_Implicit_Aliasing;
+
-----------------------------------------
-- Check_Implicit_Dynamic_Code_Allowed --
-----------------------------------------
@@ -426,7 +512,9 @@ package body Restrict is
Update_Restrictions (Restrictions);
- -- If in main extended unit, update main restrictions as well
+ -- If in main extended unit, update main restrictions as well. Note
+ -- that as usual we check for Main_Unit explicitly to deal with the
+ -- case of configuration pragma files.
if Current_Sem_Unit = Main_Unit
or else In_Extended_Main_Source_Unit (N)
@@ -570,6 +658,16 @@ package body Restrict is
for J in Cunit_Boolean_Restrictions loop
Restrictions.Set (J) := R (J);
end loop;
+
+ -- If No_Elaboration_Code set in configuration restrictions, and we
+ -- in the main extended source, then set it here now. This is part of
+ -- the special processing for No_Elaboration_Code.
+
+ if In_Extended_Main_Source_Unit (Cunit_Entity (Current_Sem_Unit))
+ and then Config_Cunit_Boolean_Restrictions (No_Elaboration_Code)
+ then
+ Restrictions.Set (No_Elaboration_Code) := True;
+ end if;
end Cunit_Boolean_Restrictions_Restore;
-------------------------------------
@@ -584,7 +682,6 @@ package body Restrict is
begin
for J in Cunit_Boolean_Restrictions loop
R (J) := Restrictions.Set (J);
- Restrictions.Set (J) := False;
end loop;
return R;
@@ -700,6 +797,26 @@ package body Restrict is
return New_Name;
end Process_Restriction_Synonyms;
+ --------------------------------------
+ -- Reset_Cunit_Boolean_Restrictions --
+ --------------------------------------
+
+ procedure Reset_Cunit_Boolean_Restrictions is
+ begin
+ for J in Cunit_Boolean_Restrictions loop
+ Restrictions.Set (J) := False;
+ end loop;
+ end Reset_Cunit_Boolean_Restrictions;
+
+ -----------------------------------------------
+ -- Restore_Config_Cunit_Boolean_Restrictions --
+ -----------------------------------------------
+
+ procedure Restore_Config_Cunit_Boolean_Restrictions is
+ begin
+ Cunit_Boolean_Restrictions_Restore (Config_Cunit_Boolean_Restrictions);
+ end Restore_Config_Cunit_Boolean_Restrictions;
+
------------------------
-- Restricted_Profile --
------------------------
@@ -932,6 +1049,15 @@ package body Restrict is
end if;
end Same_Unit;
+ --------------------------------------------
+ -- Save_Config_Cunit_Boolean_Restrictions --
+ --------------------------------------------
+
+ procedure Save_Config_Cunit_Boolean_Restrictions is
+ begin
+ Config_Cunit_Boolean_Restrictions := Cunit_Boolean_Restrictions_Save;
+ end Save_Config_Cunit_Boolean_Restrictions;
+
------------------------------
-- Set_Hidden_Part_In_SPARK --
------------------------------
@@ -998,23 +1124,6 @@ package body Restrict is
N : Node_Id)
is
begin
- -- Restriction No_Elaboration_Code must be enforced on a unit by unit
- -- basis. Hence, we avoid setting the restriction when processing an
- -- unit which is not the main one being compiled (or its corresponding
- -- spec). It can happen, for example, when processing an inlined body
- -- (the package containing the inlined subprogram is analyzed,
- -- including its pragma Restrictions).
-
- -- This seems like a very nasty kludge??? This is not the only per unit
- -- restriction why is this treated specially ???
-
- if R = No_Elaboration_Code
- and then Current_Sem_Unit /= Main_Unit
- and then Cunit (Current_Sem_Unit) /= Library_Unit (Cunit (Main_Unit))
- then
- return;
- end if;
-
Restrictions.Set (R) := True;
if Restricted_Profile_Cached and Restricted_Profile_Result then
diff --git a/gcc/ada/restrict.ads b/gcc/ada/restrict.ads
index 10875025e2b..5d03f831267 100644
--- a/gcc/ada/restrict.ads
+++ b/gcc/ada/restrict.ads
@@ -71,10 +71,6 @@ package Restrict is
-- set if Restriction_Warnings is set, so this does not look like a
-- restriction to the binder.
- type Save_Cunit_Boolean_Restrictions is private;
- -- Type used for saving and restoring compilation unit restrictions.
- -- See Cunit_Boolean_Restrictions_[Save|Restore] subprograms.
-
-- The following declarations establish a mapping between restriction
-- identifiers, and the names of corresponding restriction library units.
@@ -279,6 +275,13 @@ package Restrict is
-- Same as Check_SPARK_Restriction except there is a continuation message
-- Msg2 following the initial message Msg1.
+ procedure Check_No_Implicit_Aliasing (Obj : Node_Id);
+ -- Obj is a node for which Is_Aliased_View is True, which is being used in
+ -- a context (e.g. 'Access) where no implicit aliasing is allowed if the
+ -- restriction No_Implicit_Aliasing is set. This procedure checks for the
+ -- case where the restriction is active and Obj does not meet the required
+ -- rules for avoiding implicit aliases, and issues a restriction message.
+
procedure Check_Implicit_Dynamic_Code_Allowed (N : Node_Id);
-- Tests to see if dynamic code generation (dynamically generated
-- trampolines, in particular) is allowed by the current restrictions
@@ -305,22 +308,6 @@ package Restrict is
-- [Wide_]Wide_Character or [Wide_]Wide_String, then the restriction
-- violation is recorded, and an appropriate message given.
- function Cunit_Boolean_Restrictions_Save
- return Save_Cunit_Boolean_Restrictions;
- -- This function saves the compilation unit restriction settings, and
- -- resets them to False. This is used e.g. when compiling a with'ed
- -- unit to avoid incorrectly propagating restrictions. Note that it
- -- would not be wrong to also save and reset the partition restrictions,
- -- since the binder would catch inconsistencies, but actually it is a
- -- good thing to acquire restrictions from with'ed units if they are
- -- required to be partition wide, because it allows the restriction
- -- violation message to be given at compile time instead of link time.
-
- procedure Cunit_Boolean_Restrictions_Restore
- (R : Save_Cunit_Boolean_Restrictions);
- -- This is the corresponding restore procedure to restore restrictions
- -- previously saved by Cunit_Boolean_Restrictions_Save.
-
function Get_Restriction_Id
(N : Name_Id) return Restriction_Id;
-- Given an identifier name, determines if it is a valid restriction
@@ -428,6 +415,71 @@ package Restrict is
-- Tests if tasking operations are allowed by the current restrictions
-- settings. For tasking to be allowed Max_Tasks must be non-zero.
+ ----------------------------------------------
+ -- Handling of Boolean Compilation Switches --
+ ----------------------------------------------
+
+ -- The following declarations are used for proper saving and restoring of
+ -- restrictions for separate compilation units. There are two cases:
+
+ -- For partition-wide restrictions, we just let the restrictions pragmas
+ -- pile up, and we never reset them. We might as well detect what we can
+ -- at compile time. If e.g. a with'ed unit has a restriction for one of
+ -- the partition-wide restrictions, then the binder will enforce it on
+ -- all units in the partition, including the unit with the WITH. Although
+ -- it would not be wrong to leave this till bind time, we might as well
+ -- flag it earlier at compile time.
+
+ -- For non-partition-wide restrictions, we have quite a different state
+ -- of affairs. Here it would be quite wrong to carry a restriction from
+ -- a with'ed unit to another with'ed unit, or from a package spec to the
+ -- package body. This means that we have to reset these non-partition
+ -- wide restrictions at the start of each separate compilation unit. For
+ -- units in the extended main program, we need to reset them all to the
+ -- values set by the configuration pragma file(s). For units not in the
+ -- extended main program, e.g. with'ed units, we might as well reset all
+ -- of these restrictions to off (False). The actual initial values will
+ -- be taken from the config files active when those units are compiled
+ -- as main units.
+
+ type Save_Cunit_Boolean_Restrictions is private;
+ -- Type used for saving and restoring compilation unit restrictions.
+
+ function Cunit_Boolean_Restrictions_Save
+ return Save_Cunit_Boolean_Restrictions;
+ -- This function saves the compilation unit restriction settings, leaving
+ -- then unchanged. This is used e.g. at the start of processing a context
+ -- clause, so that the main unit restrictions can be restored after all
+ -- the with'ed units have been processed.
+
+ procedure Cunit_Boolean_Restrictions_Restore
+ (R : Save_Cunit_Boolean_Restrictions);
+ -- This is the corresponding restore procedure to restore restrictions
+ -- previously saved by Cunit_Boolean_Restrictions_Save. However it does
+ -- not reset No_Elaboration_Code, this stays set if it was set before
+ -- the call, and also if it is set before the call, then the Config
+ -- setting is also updated to include this restriction. This is what
+ -- implements the special handling of No_Elaboration_Code.
+
+ procedure Save_Config_Cunit_Boolean_Restrictions;
+ -- This saves the current compilation unit restrictions in an internal
+ -- variable, and leaves them unchanged. This is called immediately after
+ -- processing the configuration file pragmas, to record the restrictions
+ -- set by these configuration file pragmas.
+
+ procedure Restore_Config_Cunit_Boolean_Restrictions;
+ -- This restores the value saved by the previous call to save config values
+ -- saved by Save_Config_Cunit_Boolean_Restrictions. It is called at the
+ -- start of processing a new unit that is part of the main sources (e.g.
+ -- a package spec when the main unit is a package body).
+
+ procedure Reset_Cunit_Boolean_Restrictions;
+ -- Turns off all non-partition-wide boolean restrictions
+
+ procedure Add_To_Config_Boolean_Restrictions (R : Restriction_Id);
+ -- Add specified restriction to stored configuration boolean restrictions.
+ -- This is used for handling the special case of No_Elaboration_Code.
+
private
type Save_Cunit_Boolean_Restrictions is
array (Cunit_Boolean_Restrictions) of Boolean;
diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads
index b7a02066b77..261365d9292 100644
--- a/gcc/ada/rtsfind.ads
+++ b/gcc/ada/rtsfind.ads
@@ -1353,6 +1353,7 @@ package Rtsfind is
RE_Allocate_Any_Controlled, -- System.Storage_Pools.Subpools
RE_Deallocate_Any_Controlled, -- System.Storage_Pools.Subpools
+ RE_Header_Size_With_Padding, -- System.Storage_Pools.Subpools
RE_Root_Storage_Pool_With_Subpools, -- System.Storage_Pools.Subpools
RE_Root_Subpool, -- System.Storage_Pools.Subpools
RE_Subpool_Handle, -- System.Storage_Pools.Subpools
@@ -2550,6 +2551,7 @@ package Rtsfind is
RE_Allocate_Any_Controlled => System_Storage_Pools_Subpools,
RE_Deallocate_Any_Controlled => System_Storage_Pools_Subpools,
+ RE_Header_Size_With_Padding => System_Storage_Pools_Subpools,
RE_Root_Storage_Pool_With_Subpools => System_Storage_Pools_Subpools,
RE_Root_Subpool => System_Storage_Pools_Subpools,
RE_Subpool_Handle => System_Storage_Pools_Subpools,
diff --git a/gcc/ada/s-atocou-builtin.adb b/gcc/ada/s-atocou-builtin.adb
index 8ec851e8f20..f230721af00 100644
--- a/gcc/ada/s-atocou-builtin.adb
+++ b/gcc/ada/s-atocou-builtin.adb
@@ -50,7 +50,12 @@ package body System.Atomic_Counters is
function Decrement (Item : in out Atomic_Counter) return Boolean is
begin
- return Sync_Sub_And_Fetch (Item.Value'Access, 1) = 0;
+ -- Note: the use of Unrestricted_Access here is required because we
+ -- are obtaining an access-to-volatile pointer to a non-volatile object.
+ -- This is not allowed for [Unchecked_]Access, but is safe in this case
+ -- because we know that no aliases are being created.
+
+ return Sync_Sub_And_Fetch (Item.Value'Unrestricted_Access, 1) = 0;
end Decrement;
---------------
@@ -59,7 +64,12 @@ package body System.Atomic_Counters is
procedure Increment (Item : in out Atomic_Counter) is
begin
- Sync_Add_And_Fetch (Item.Value'Access, 1);
+ -- Note: the use of Unrestricted_Access here is required because we
+ -- are obtaining an access-to-volatile pointer to a non-volatile object.
+ -- This is not allowed for [Unchecked_]Access, but is safe in this case
+ -- because we know that no aliases are being created.
+
+ Sync_Add_And_Fetch (Item.Value'Unrestricted_Access, 1);
end Increment;
------------
diff --git a/gcc/ada/s-finmas.adb b/gcc/ada/s-finmas.adb
index 8474ff4a8f3..918519b6781 100644
--- a/gcc/ada/s-finmas.adb
+++ b/gcc/ada/s-finmas.adb
@@ -181,6 +181,12 @@ package body System.Finalization_Masters is
if Master.Finalization_Started then
Unlock_Task.all;
+
+ -- Double finalization may occur during the handling of stand alone
+ -- libraries or the finalization of a pool with subpools. Due to the
+ -- potential aliasing of masters in these two cases, do not process
+ -- the same master twice.
+
return;
end if;
diff --git a/gcc/ada/s-os_lib.ads b/gcc/ada/s-os_lib.ads
index 1c63e386ea9..3599261498c 100755
--- a/gcc/ada/s-os_lib.ads
+++ b/gcc/ada/s-os_lib.ads
@@ -174,7 +174,7 @@ package System.OS_Lib is
-- File descriptors for standard input output files
Invalid_FD : constant File_Descriptor := -1;
- -- File descriptor returned when error in opening/creating file;
+ -- File descriptor returned when error in opening/creating file
type Mode is (Binary, Text);
for Mode'Size use Integer'Size;
diff --git a/gcc/ada/s-oscons-tmplt.c b/gcc/ada/s-oscons-tmplt.c
index ad3d06520d8..3d70ceb4857 100644
--- a/gcc/ada/s-oscons-tmplt.c
+++ b/gcc/ada/s-oscons-tmplt.c
@@ -97,6 +97,7 @@ pragma Style_Checks ("M32766");
#include <string.h>
#include <limits.h>
#include <fcntl.h>
+#include <time.h>
#if defined (__alpha__) && defined (__osf__)
/** Tru64 is unable to do vector IO operations with default value of IOV_MAX,
@@ -145,7 +146,7 @@ pragma Style_Checks ("M32766");
# define NATIVE
-#endif
+#endif /* DUMMY */
#ifndef TARGET
# error Please define TARGET
@@ -212,7 +213,7 @@ int counter = 0;
: : "i" (__LINE__));
/* Freeform text */
-#endif
+#endif /* NATIVE */
#define CST(name,comment) C(#name,String,name,comment)
@@ -925,6 +926,21 @@ CND(VEOL2, "Alternative EOL")
#endif /* HAVE_TERMIOS */
+/*
+
+ -----------------------------
+ -- Pseudo terminal library --
+ -----------------------------
+
+*/
+
+#if defined (__FreeBSD__) || defined (linux)
+# define PTY_Library "-lutil"
+#else
+# define PTY_Library ""
+#endif
+CST(PTY_Library, "for g-exptty")
+
/**
** Sockets constants
**/
@@ -1317,58 +1333,71 @@ CST(Inet_Pton_Linkname, "")
#endif /* HAVE_SOCKETS */
-/**
- ** System-specific constants follow
- ** Each section should be activated if compiling for the corresponding
- ** platform *or* generating the dummy version for runtime test compilation.
- **/
-
-#if defined (__vxworks) || defined (DUMMY)
-
/*
- --------------------------------
- -- VxWorks-specific constants --
- --------------------------------
+ ---------------------
+ -- Threads support --
+ ---------------------
+
+ -- Clock identifier definitions
- -- These constants may be used only within the VxWorks version of
- -- GNAT.Sockets.Thin.
*/
-CND(OK, "VxWorks generic success")
-CND(ERROR, "VxWorks generic error")
+#ifdef CLOCK_REALTIME
+CND(CLOCK_REALTIME, "System realtime clock")
+#endif
+#ifdef CLOCK_MONOTONIC
+CND(CLOCK_MONOTONIC, "System monotonic clock")
#endif
-#if defined (__MINGW32__) || defined (DUMMY)
-/*
+#ifdef CLOCK_FASTEST
+CND(CLOCK_FASTEST, "Fastest clock")
+#endif
- ------------------------------
- -- MinGW-specific constants --
- ------------------------------
+#if defined (__sgi)
+CND(CLOCK_SGI_FAST, "SGI fast clock")
+CND(CLOCK_SGI_CYCLE, "SGI CPU clock")
+#endif
- -- These constants may be used only within the MinGW version of
- -- GNAT.Sockets.Thin.
-*/
+#ifndef CLOCK_THREAD_CPUTIME_ID
+# define CLOCK_THREAD_CPUTIME_ID -1
+#endif
+CND(CLOCK_THREAD_CPUTIME_ID, "Thread CPU clock")
-CND(WSASYSNOTREADY, "System not ready")
-CND(WSAVERNOTSUPPORTED, "Version not supported")
-CND(WSANOTINITIALISED, "Winsock not initialized")
-CND(WSAEDISCON, "Disconnected")
+#if defined(__APPLE__)
+/* There's no clock_gettime or clock_id's on Darwin, generate a dummy value */
+# define CLOCK_RT_Ada "-1"
+#elif defined(FreeBSD) || (defined(_AIX) && defined(_AIXVERSION_530))
+/** On these platforms use system provided monotonic clock instead of
+ ** the default CLOCK_REALTIME. We then need to set up cond var attributes
+ ** appropriately (see thread.c).
+ **/
+# define CLOCK_RT_Ada "CLOCK_MONOTONIC"
+# define NEED_PTHREAD_CONDATTR_SETCLOCK
+
+#elif defined(CLOCK_REALTIME)
+/* By default use CLOCK_REALTIME */
+# define CLOCK_RT_Ada "CLOCK_REALTIME"
#endif
-#ifdef NATIVE
- putchar ('\n');
+#ifdef CLOCK_RT_Ada
+CNS(CLOCK_RT_Ada, "")
#endif
#if defined (__APPLE__) || defined (__linux__) || defined (DUMMY)
/*
- -- Sizes of pthread data types (on Darwin these are padding)
+ -- Sizes of pthread data types
+
*/
#if defined (__APPLE__) || defined (DUMMY)
+/*
+ -- (on Darwin, these are just placeholders)
+
+*/
#define PTHREAD_SIZE __PTHREAD_SIZE__
#define PTHREAD_ATTR_SIZE __PTHREAD_ATTR_SIZE__
#define PTHREAD_MUTEXATTR_SIZE __PTHREAD_MUTEXATTR_SIZE__
@@ -1390,24 +1419,65 @@ CND(WSAEDISCON, "Disconnected")
#define PTHREAD_ONCE_SIZE (sizeof (pthread_once_t))
#endif
-CND(PTHREAD_SIZE, "pthread_t")
+CND(PTHREAD_SIZE, "pthread_t")
+CND(PTHREAD_ATTR_SIZE, "pthread_attr_t")
+CND(PTHREAD_MUTEXATTR_SIZE, "pthread_mutexattr_t")
+CND(PTHREAD_MUTEX_SIZE, "pthread_mutex_t")
+CND(PTHREAD_CONDATTR_SIZE, "pthread_condattr_t")
+CND(PTHREAD_COND_SIZE, "pthread_cond_t")
+CND(PTHREAD_RWLOCKATTR_SIZE, "pthread_rwlockattr_t")
+CND(PTHREAD_RWLOCK_SIZE, "pthread_rwlock_t")
+CND(PTHREAD_ONCE_SIZE, "pthread_once_t")
-CND(PTHREAD_ATTR_SIZE, "pthread_attr_t")
+#endif /* __APPLE__ || __linux__ */
-CND(PTHREAD_MUTEXATTR_SIZE, "pthread_mutexattr_t")
+/**
+ ** System-specific constants follow
+ ** Each section should be activated if compiling for the corresponding
+ ** platform *or* generating the dummy version for runtime test compilation.
+ **/
-CND(PTHREAD_MUTEX_SIZE, "pthread_mutex_t")
+#if defined (__vxworks) || defined (DUMMY)
-CND(PTHREAD_CONDATTR_SIZE, "pthread_condattr_t")
+/*
-CND(PTHREAD_COND_SIZE, "pthread_cond_t")
+ --------------------------------
+ -- VxWorks-specific constants --
+ --------------------------------
-CND(PTHREAD_RWLOCKATTR_SIZE, "pthread_rwlockattr_t")
+ -- These constants may be used only within the VxWorks version of
+ -- GNAT.Sockets.Thin.
+*/
+
+CND(OK, "VxWorks generic success")
+CND(ERROR, "VxWorks generic error")
+
+#endif /* __vxworks */
+
+#if defined (__MINGW32__) || defined (DUMMY)
+/*
-CND(PTHREAD_RWLOCK_SIZE, "pthread_rwlock_t")
+ ------------------------------
+ -- MinGW-specific constants --
+ ------------------------------
-CND(PTHREAD_ONCE_SIZE, "pthread_once_t")
+ -- These constants may be used only within the MinGW version of
+ -- GNAT.Sockets.Thin.
+*/
+CND(WSASYSNOTREADY, "System not ready")
+CND(WSAVERNOTSUPPORTED, "Version not supported")
+CND(WSANOTINITIALISED, "Winsock not initialized")
+CND(WSAEDISCON, "Disconnected")
+
+#endif /* __MINGW32__ */
+
+/**
+ ** End of constants definitions
+ **/
+
+#ifdef NATIVE
+ putchar ('\n');
#endif
/*
diff --git a/gcc/ada/s-osinte-aix.ads b/gcc/ada/s-osinte-aix.ads
index c8e66082604..c89e7296e14 100644
--- a/gcc/ada/s-osinte-aix.ads
+++ b/gcc/ada/s-osinte-aix.ads
@@ -197,10 +197,7 @@ package System.OS_Interface is
type timespec is private;
- type clockid_t is private;
-
- CLOCK_REALTIME : constant clockid_t;
- CLOCK_MONOTONIC : constant clockid_t;
+ type clockid_t is new int;
function clock_gettime
(clock_id : clockid_t;
@@ -547,10 +544,6 @@ private
end record;
pragma Convention (C, timespec);
- type clockid_t is new int;
- CLOCK_REALTIME : constant clockid_t := 9;
- CLOCK_MONOTONIC : constant clockid_t := 10;
-
type pthread_attr_t is new System.Address;
pragma Convention (C, pthread_attr_t);
-- typedef struct __pt_attr *pthread_attr_t;
diff --git a/gcc/ada/s-osinte-darwin.ads b/gcc/ada/s-osinte-darwin.ads
index fe2a10a3315..ff0480379bc 100644
--- a/gcc/ada/s-osinte-darwin.ads
+++ b/gcc/ada/s-osinte-darwin.ads
@@ -183,10 +183,7 @@ package System.OS_Interface is
type timespec is private;
- type clockid_t is private;
-
- CLOCK_REALTIME : constant clockid_t;
- CLOCK_MONOTONIC : constant clockid_t;
+ type clockid_t is new int;
function clock_gettime
(clock_id : clockid_t;
@@ -524,10 +521,6 @@ private
end record;
pragma Convention (C, timespec);
- type clockid_t is new int;
- CLOCK_REALTIME : constant clockid_t := 0;
- CLOCK_MONOTONIC : constant clockid_t := CLOCK_REALTIME;
-
--
-- Darwin specific signal implementation
--
diff --git a/gcc/ada/s-osinte-freebsd.ads b/gcc/ada/s-osinte-freebsd.ads
index cbd2a2df428..b581dae2e20 100644
--- a/gcc/ada/s-osinte-freebsd.ads
+++ b/gcc/ada/s-osinte-freebsd.ads
@@ -200,10 +200,7 @@ package System.OS_Interface is
function nanosleep (rqtp, rmtp : access timespec) return int;
pragma Import (C, nanosleep, "nanosleep");
- type clockid_t is private;
-
- CLOCK_REALTIME : constant clockid_t;
- CLOCK_MONOTONIC : constant clockid_t;
+ type clockid_t is new int;
function clock_gettime
(clock_id : clockid_t;
@@ -643,13 +640,6 @@ private
end record;
pragma Convention (C, timespec);
- type clockid_t is new int;
- CLOCK_REALTIME : constant clockid_t := 0;
- CLOCK_MONOTONIC : constant clockid_t := 0;
- -- On FreeBSD, pthread_cond_timedwait assumes a CLOCK_REALTIME time by
- -- default (unless pthread_condattr_setclock is used to set an alternate
- -- clock).
-
type pthread_t is new System.Address;
type pthread_attr_t is new System.Address;
type pthread_mutex_t is new System.Address;
diff --git a/gcc/ada/s-osinte-hpux-dce.ads b/gcc/ada/s-osinte-hpux-dce.ads
index f39cbfdec34..3d873e1163c 100644
--- a/gcc/ada/s-osinte-hpux-dce.ads
+++ b/gcc/ada/s-osinte-hpux-dce.ads
@@ -7,7 +7,7 @@
-- S p e c --
-- --
-- Copyright (C) 1991-1994, Florida State University --
--- Copyright (C) 1995-2009, 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 --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -193,9 +193,7 @@ package System.OS_Interface is
function nanosleep (rqtp, rmtp : access timespec) return int;
pragma Import (C, nanosleep);
- type clockid_t is private;
-
- CLOCK_REALTIME : constant clockid_t;
+ type clockid_t is new int;
function Clock_Gettime
(Clock_Id : clockid_t; Tp : access timespec) return int;
diff --git a/gcc/ada/s-osinte-hpux.ads b/gcc/ada/s-osinte-hpux.ads
index bc9a7091d6f..55729f877ab 100644
--- a/gcc/ada/s-osinte-hpux.ads
+++ b/gcc/ada/s-osinte-hpux.ads
@@ -180,10 +180,7 @@ package System.OS_Interface is
type timespec is private;
- type clockid_t is private;
-
- CLOCK_REALTIME : constant clockid_t;
- CLOCK_MONOTONIC : constant clockid_t;
+ type clockid_t is new int;
function clock_gettime
(clock_id : clockid_t;
@@ -529,10 +526,6 @@ private
end record;
pragma Convention (C, timespec);
- type clockid_t is new int;
- CLOCK_REALTIME : constant clockid_t := 1;
- CLOCK_MONOTONIC : constant clockid_t := CLOCK_REALTIME;
-
type pthread_attr_t is new int;
type pthread_condattr_t is new int;
type pthread_mutexattr_t is new int;
diff --git a/gcc/ada/s-osinte-irix.ads b/gcc/ada/s-osinte-irix.ads
index ddeadcb6147..365a3de2dca 100644
--- a/gcc/ada/s-osinte-irix.ads
+++ b/gcc/ada/s-osinte-irix.ads
@@ -172,11 +172,7 @@ package System.OS_Interface is
type timespec is private;
type timespec_ptr is access all timespec;
- type clockid_t is private;
-
- CLOCK_REALTIME : constant clockid_t;
- CLOCK_SGI_FAST : constant clockid_t;
- CLOCK_SGI_CYCLE : constant clockid_t;
+ type clockid_t is new int;
SGI_CYCLECNTR_SIZE : constant := 165;
@@ -486,11 +482,6 @@ private
end record;
pragma Convention (C, timespec);
- type clockid_t is new int;
- CLOCK_REALTIME : constant clockid_t := 1;
- CLOCK_SGI_CYCLE : constant clockid_t := 2;
- CLOCK_SGI_FAST : constant clockid_t := 3;
-
type array_type_9 is array (Integer range 0 .. 4) of long;
type pthread_attr_t is record
X_X_D : array_type_9;
diff --git a/gcc/ada/s-osinte-lynxos-3.ads b/gcc/ada/s-osinte-lynxos-3.ads
index 3d912eefee2..e8288d9f6dd 100644
--- a/gcc/ada/s-osinte-lynxos-3.ads
+++ b/gcc/ada/s-osinte-lynxos-3.ads
@@ -177,9 +177,7 @@ package System.OS_Interface is
type timespec is private;
- type clockid_t is private;
-
- CLOCK_REALTIME : constant clockid_t;
+ type clockid_t is new int;
function clock_gettime
(clock_id : clockid_t;
@@ -516,9 +514,6 @@ private
end record;
pragma Convention (C, timespec);
- type clockid_t is new unsigned_char;
- CLOCK_REALTIME : constant clockid_t := 0;
-
type st_t is record
stksize : int;
prio : int;
diff --git a/gcc/ada/s-osinte-lynxos.ads b/gcc/ada/s-osinte-lynxos.ads
index 8b998bcfdf6..7bcbab6072e 100644
--- a/gcc/ada/s-osinte-lynxos.ads
+++ b/gcc/ada/s-osinte-lynxos.ads
@@ -197,10 +197,7 @@ package System.OS_Interface is
type timespec is private;
- type clockid_t is private;
-
- CLOCK_REALTIME : constant clockid_t;
- CLOCK_MONOTONIC : constant clockid_t;
+ type clockid_t is new int;
function clock_gettime
(clock_id : clockid_t;
@@ -517,10 +514,6 @@ private
end record;
pragma Convention (C, timespec);
- type clockid_t is new unsigned_char;
- CLOCK_REALTIME : constant clockid_t := 1;
- CLOCK_MONOTONIC : constant clockid_t := CLOCK_REALTIME;
-
type st_attr_t is record
stksize : int;
prio : int;
diff --git a/gcc/ada/s-osinte-solaris-posix.ads b/gcc/ada/s-osinte-solaris-posix.ads
index 8781a12dd67..eb17bd4e25f 100644
--- a/gcc/ada/s-osinte-solaris-posix.ads
+++ b/gcc/ada/s-osinte-solaris-posix.ads
@@ -187,10 +187,7 @@ package System.OS_Interface is
type timespec is private;
- type clockid_t is private;
-
- CLOCK_REALTIME : constant clockid_t;
- CLOCK_MONOTONIC : constant clockid_t;
+ type clockid_t is new int;
function clock_gettime
(clock_id : clockid_t;
@@ -520,10 +517,6 @@ private
end record;
pragma Convention (C, timespec);
- type clockid_t is new int;
- CLOCK_REALTIME : constant clockid_t := 3;
- CLOCK_MONOTONIC : constant clockid_t := CLOCK_REALTIME;
-
type pthread_attr_t is record
pthread_attrp : System.Address;
end record;
diff --git a/gcc/ada/s-osinte-solaris.ads b/gcc/ada/s-osinte-solaris.ads
index 03a0c4ae47d..b4baa6d4998 100644
--- a/gcc/ada/s-osinte-solaris.ads
+++ b/gcc/ada/s-osinte-solaris.ads
@@ -243,9 +243,7 @@ package System.OS_Interface is
type timespec is private;
- type clockid_t is private;
-
- CLOCK_REALTIME : constant clockid_t;
+ type clockid_t is new int;
function clock_gettime
(clock_id : clockid_t; tp : access timespec) return int;
@@ -531,9 +529,6 @@ private
end record;
pragma Convention (C, timespec);
- type clockid_t is new int;
- CLOCK_REALTIME : constant clockid_t := 0;
-
type array_type_9 is array (0 .. 3) of unsigned_char;
type record_type_3 is record
flag : array_type_9;
diff --git a/gcc/ada/s-osinte-tru64.ads b/gcc/ada/s-osinte-tru64.ads
index 83471727b1b..0fcd4221e80 100644
--- a/gcc/ada/s-osinte-tru64.ads
+++ b/gcc/ada/s-osinte-tru64.ads
@@ -7,7 +7,7 @@
-- S p e c --
-- --
-- Copyright (C) 1991-1994, Florida State University --
--- Copyright (C) 1995-2010, Free Software Foundation, Inc. --
+-- Copyright (C) 1995-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- --
@@ -191,9 +191,7 @@ package System.OS_Interface is
function nanosleep (rqtp, rmtp : access timespec) return int;
pragma Import (C, nanosleep);
- type clockid_t is private;
-
- CLOCK_REALTIME : constant clockid_t;
+ type clockid_t is new int;
function clock_gettime
(clock_id : clockid_t;
@@ -506,9 +504,6 @@ private
end record;
pragma Convention (C, timespec);
- type clockid_t is new int;
- CLOCK_REALTIME : constant clockid_t := 1;
-
type unsigned_long_array is array (Natural range <>) of unsigned_long;
type pthread_t is new System.Address;
diff --git a/gcc/ada/s-osinte-vxworks.ads b/gcc/ada/s-osinte-vxworks.ads
index f5013ea6977..19976740463 100644
--- a/gcc/ada/s-osinte-vxworks.ads
+++ b/gcc/ada/s-osinte-vxworks.ads
@@ -243,9 +243,7 @@ package System.OS_Interface is
end record;
pragma Convention (C, timespec);
- type clockid_t is private;
-
- CLOCK_REALTIME : constant clockid_t; -- System wide realtime clock
+ type clockid_t is new int;
function To_Duration (TS : timespec) return Duration;
pragma Inline (To_Duration);
@@ -511,8 +509,5 @@ private
ERROR_PID : constant pid_t := -1;
- type clockid_t is new int;
- CLOCK_REALTIME : constant clockid_t := 0;
-
type sigset_t is new System.VxWorks.Ext.sigset_t;
end System.OS_Interface;
diff --git a/gcc/ada/s-osprim-vxworks.adb b/gcc/ada/s-osprim-vxworks.adb
index f75850af026..1eccae5612a 100644
--- a/gcc/ada/s-osprim-vxworks.adb
+++ b/gcc/ada/s-osprim-vxworks.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1998-2009, Free Software Foundation, Inc. --
+-- Copyright (C) 1998-2011, Free Software Foundation, Inc. --
-- --
-- GNARL 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- --
@@ -37,6 +37,7 @@ with System.OS_Interface;
-- set of C imported routines: using Ada routines from this package would
-- create a dependency on libgnarl in libgnat, which is not desirable.
+with System.OS_Constants;
with Interfaces.C;
package body System.OS_Primitives is
@@ -44,6 +45,8 @@ package body System.OS_Primitives is
use System.OS_Interface;
use type Interfaces.C.int;
+ package OSC renames System.OS_Constants;
+
------------------------
-- Internal functions --
------------------------
@@ -94,7 +97,7 @@ package body System.OS_Primitives is
TS : aliased timespec;
Result : int;
begin
- Result := clock_gettime (CLOCK_REALTIME, TS'Unchecked_Access);
+ Result := clock_gettime (OSC.CLOCK_RT_Ada, TS'Unchecked_Access);
pragma Assert (Result = 0);
return Duration (TS.ts_sec) + Duration (TS.ts_nsec) / 10#1#E9;
end Clock;
diff --git a/gcc/ada/s-rident.ads b/gcc/ada/s-rident.ads
index 1c306e34664..d067f3d7f4f 100644
--- a/gcc/ada/s-rident.ads
+++ b/gcc/ada/s-rident.ads
@@ -124,7 +124,15 @@ package System.Rident is
No_Default_Initialization, -- GNAT
- -- The following cases do not require consistency checking
+ -- The following cases do not require consistency checking and if used
+ -- as a configuration pragma within a specific unit, apply only to that
+ -- unit (e.g. if used in the package spec, do not apply to the body)
+
+ -- Note: No_Elaboration_Code is handled specially. Like the other
+ -- non-partition-wide restrictions, it can only be set in a unit that
+ -- is part of the extended main source unit (body/spec/subunits). But
+ -- it is sticky, in that if it is found anywhere within any of these
+ -- units, it applies to all units in this extended main source.
Immediate_Reclamation, -- (RM H.4(10))
No_Implementation_Aspect_Specifications, -- Ada 2012 AI-241
@@ -202,7 +210,7 @@ package System.Rident is
-- Boolean restrictions that are not checked for partition consistency
-- and that thus apply only to the current unit. Note that for these
-- restrictions, the compiler does not apply restrictions found in
- -- with'ed units, parent specs etc. to the main unit.
+ -- with'ed units, parent specs etc. to the main unit, and vice versa.
subtype All_Parameter_Restrictions is
Restriction_Id range
diff --git a/gcc/ada/s-stposu.adb b/gcc/ada/s-stposu.adb
index 4bbff767d96..78958412ab2 100644
--- a/gcc/ada/s-stposu.adb
+++ b/gcc/ada/s-stposu.adb
@@ -56,12 +56,6 @@ package body System.Storage_Pools.Subpools is
procedure Detach (N : not null SP_Node_Ptr);
-- Unhook a subpool node from an arbitrary subpool list
- function Nearest_Multiple_Rounded_Up
- (Size : Storage_Count;
- Alignment : Storage_Count) return Storage_Count;
- -- Given arbitrary values of storage size and alignment, calculate the
- -- nearest multiple of the alignment rounded up where size can fit.
-
--------------
-- Allocate --
--------------
@@ -218,10 +212,7 @@ package body System.Storage_Pools.Subpools is
-- Account for possible padding space before the header due to a
-- larger alignment.
- Header_And_Padding :=
- Nearest_Multiple_Rounded_Up
- (Size => Header_Size,
- Alignment => Alignment);
+ Header_And_Padding := Header_Size_With_Padding (Alignment);
N_Size := Storage_Size + Header_And_Padding;
@@ -388,10 +379,7 @@ package body System.Storage_Pools.Subpools is
-- Account for possible padding space before the header due to a
-- larger alignment.
- Header_And_Padding :=
- Nearest_Multiple_Rounded_Up
- (Size => Header_Size,
- Alignment => Alignment);
+ Header_And_Padding := Header_Size_With_Padding (Alignment);
-- N_Addr N_Ptr Addr (from input)
-- | | |
@@ -571,6 +559,28 @@ package body System.Storage_Pools.Subpools is
Free (Subpool.Node);
end Finalize_Subpool;
+ ------------------------------
+ -- Header_Size_With_Padding --
+ ------------------------------
+
+ function Header_Size_With_Padding
+ (Alignment : System.Storage_Elements.Storage_Count)
+ return System.Storage_Elements.Storage_Count
+ is
+ Size : constant Storage_Count := Header_Size;
+
+ begin
+ if Size mod Alignment = 0 then
+ return Size;
+
+ -- Add enough padding to reach the nearest multiple of the alignment
+ -- rounding up.
+
+ else
+ return ((Size + Alignment - 1) / Alignment) * Alignment;
+ end if;
+ end Header_Size_With_Padding;
+
----------------
-- Initialize --
----------------
@@ -592,26 +602,6 @@ package body System.Storage_Pools.Subpools is
Pool.Subpools.Prev := Pool.Subpools'Unchecked_Access;
end Initialize_Pool;
- ---------------------------------
- -- Nearest_Multiple_Rounded_Up --
- ---------------------------------
-
- function Nearest_Multiple_Rounded_Up
- (Size : Storage_Count;
- Alignment : Storage_Count) return Storage_Count
- is
- begin
- if Size mod Alignment = 0 then
- return Size;
-
- -- Add enough padding to reach the nearest multiple of the alignment
- -- rounding up.
-
- else
- return ((Size + Alignment - 1) / Alignment) * Alignment;
- end if;
- end Nearest_Multiple_Rounded_Up;
-
---------------------
-- Pool_Of_Subpool --
---------------------
diff --git a/gcc/ada/s-stposu.ads b/gcc/ada/s-stposu.ads
index 0c5bd218515..38f8cfc73a3 100644
--- a/gcc/ada/s-stposu.ads
+++ b/gcc/ada/s-stposu.ads
@@ -329,6 +329,13 @@ private
-- subpool from its owner's list. Deallocate the associated doubly linked
-- list node.
+ function Header_Size_With_Padding
+ (Alignment : System.Storage_Elements.Storage_Count)
+ return System.Storage_Elements.Storage_Count;
+ -- Given an arbitrary alignment, calculate the size of the header which
+ -- precedes a controlled object as the nearest multiple rounded up of the
+ -- alignment.
+
overriding procedure Initialize (Controller : in out Pool_Controller);
-- Buffer routine, calls Initialize_Pool
diff --git a/gcc/ada/s-taprop-hpux-dce.adb b/gcc/ada/s-taprop-hpux-dce.adb
index 346de43ba05..1c5dcc1a024 100644
--- a/gcc/ada/s-taprop-hpux-dce.adb
+++ b/gcc/ada/s-taprop-hpux-dce.adb
@@ -44,6 +44,7 @@ with Interfaces.C;
with System.Tasking.Debug;
with System.Interrupt_Management;
+with System.OS_Constants;
with System.OS_Primitives;
with System.Task_Primitives.Interrupt_Operations;
@@ -60,6 +61,7 @@ with System.Soft_Links;
package body System.Task_Primitives.Operations is
+ package OSC renames System.OS_Constants;
package SSL renames System.Soft_Links;
use System.Tasking.Debug;
@@ -555,7 +557,7 @@ package body System.Task_Primitives.Operations is
TS : aliased timespec;
Result : Interfaces.C.int;
begin
- Result := Clock_Gettime (CLOCK_REALTIME, TS'Unchecked_Access);
+ Result := Clock_Gettime (OSC.CLOCK_RT_Ada, TS'Unchecked_Access);
pragma Assert (Result = 0);
return To_Duration (TS);
end Monotonic_Clock;
diff --git a/gcc/ada/s-taprop-irix.adb b/gcc/ada/s-taprop-irix.adb
index 5b4d4bef16e..8893c010571 100644
--- a/gcc/ada/s-taprop-irix.adb
+++ b/gcc/ada/s-taprop-irix.adb
@@ -45,6 +45,7 @@ with Interfaces.C;
with System.Task_Info;
with System.Tasking.Debug;
with System.Interrupt_Management;
+with System.OS_Constants;
with System.OS_Primitives;
with System.IO;
@@ -56,6 +57,7 @@ with System.Soft_Links;
package body System.Task_Primitives.Operations is
+ package OSC renames System.OS_Constants;
package SSL renames System.Soft_Links;
use System.Tasking;
@@ -89,8 +91,6 @@ package body System.Task_Primitives.Operations is
Dispatching_Policy : Character;
pragma Import (C, Dispatching_Policy, "__gl_task_dispatching_policy");
- Real_Time_Clock_Id : constant clockid_t := CLOCK_REALTIME;
-
Unblocked_Signal_Mask : aliased sigset_t;
Foreign_Task_Elaborated : aliased Boolean := True;
@@ -572,7 +572,7 @@ package body System.Task_Primitives.Operations is
TS : aliased timespec;
Result : Interfaces.C.int;
begin
- Result := clock_gettime (Real_Time_Clock_Id, TS'Unchecked_Access);
+ Result := clock_gettime (OSC.CLOCK_RT_Ada, TS'Unchecked_Access);
pragma Assert (Result = 0);
return To_Duration (TS);
end Monotonic_Clock;
@@ -583,7 +583,7 @@ package body System.Task_Primitives.Operations is
function RT_Resolution return Duration is
begin
- -- The clock_getres (Real_Time_Clock_Id) function appears to return
+ -- The clock_getres (OSC.CLOCK_RT_Ada) function appears to return
-- the interrupt resolution of the realtime clock and not the actual
-- resolution of reading the clock. Even though this last value is
-- only guaranteed to be 100 Hz, at least the Origin 200 appears to
@@ -836,9 +836,15 @@ package body System.Task_Primitives.Operations is
-- do not need to manipulate caller's signal mask at this point.
-- All tasks in RTS will have All_Tasks_Mask initially.
+ -- Note: the use of Unrestricted_Access in the following call is needed
+ -- because otherwise we have an error of getting a access-to-volatile
+ -- value which points to a non-volatile object. But in this case it is
+ -- safe to do this, since we know we have no problems with aliasing and
+ -- Unrestricted_Access bypasses this check.
+
Result :=
pthread_create
- (T.Common.LL.Thread'Access,
+ (T.Common.LL.Thread'Unrestricted_Access,
Attributes'Access,
Thread_Body_Access (Wrapper),
To_Address (T));
@@ -865,9 +871,15 @@ package body System.Task_Primitives.Operations is
(Attributes'Access, To_Int (T.Common.Task_Info.Scope));
pragma Assert (Result = 0);
+ -- Note: the use of Unrestricted_Access in the following call
+ -- is needed because otherwise we have an error of getting a
+ -- access-to-volatile value which points to a non-volatile object.
+ -- But in this case it is safe to do this, since we know we have no
+ -- aliasing problems and Unrestricted_Access bypasses this check.
+
Result :=
pthread_create
- (T.Common.LL.Thread'Access,
+ (T.Common.LL.Thread'Unrestricted_Access,
Attributes'Access,
Thread_Body_Access (Wrapper),
To_Address (T));
diff --git a/gcc/ada/s-taprop-linux.adb b/gcc/ada/s-taprop-linux.adb
index c63d5531b62..4e69ea4b321 100644
--- a/gcc/ada/s-taprop-linux.adb
+++ b/gcc/ada/s-taprop-linux.adb
@@ -291,14 +291,10 @@ package body System.Task_Primitives.Operations is
else
declare
- Mutex_Attr : aliased pthread_mutexattr_t;
- Result : Interfaces.C.int;
+ Result : Interfaces.C.int;
begin
- Result := pthread_mutexattr_init (Mutex_Attr'Access);
- pragma Assert (Result = 0);
-
- Result := pthread_mutex_init (L.WO'Access, Mutex_Attr'Access);
+ Result := pthread_mutex_init (L.WO'Access, null);
pragma Assert (Result = 0 or else Result = ENOMEM);
@@ -315,14 +311,10 @@ package body System.Task_Primitives.Operations is
is
pragma Unreferenced (Level);
- Mutex_Attr : aliased pthread_mutexattr_t;
- Result : Interfaces.C.int;
+ Result : Interfaces.C.int;
begin
- Result := pthread_mutexattr_init (Mutex_Attr'Access);
- pragma Assert (Result = 0);
-
- Result := pthread_mutex_init (L, Mutex_Attr'Access);
+ Result := pthread_mutex_init (L, null);
pragma Assert (Result = 0 or else Result = ENOMEM);
@@ -817,9 +809,8 @@ package body System.Task_Primitives.Operations is
--------------------
procedure Initialize_TCB (Self_ID : Task_Id; Succeeded : out Boolean) is
- Mutex_Attr : aliased pthread_mutexattr_t;
- Cond_Attr : aliased pthread_condattr_t;
- Result : Interfaces.C.int;
+ Cond_Attr : aliased pthread_condattr_t;
+ Result : Interfaces.C.int;
begin
-- Give the task a unique serial number
@@ -831,11 +822,8 @@ package body System.Task_Primitives.Operations is
Self_ID.Common.LL.Thread := Null_Thread_Id;
if not Single_Lock then
- Result := pthread_mutexattr_init (Mutex_Attr'Access);
- pragma Assert (Result = 0);
-
Result :=
- pthread_mutex_init (Self_ID.Common.LL.L'Access, Mutex_Attr'Access);
+ pthread_mutex_init (Self_ID.Common.LL.L'Access, null);
pragma Assert (Result = 0 or else Result = ENOMEM);
if Result /= 0 then
@@ -1002,11 +990,18 @@ package body System.Task_Primitives.Operations is
-- do not need to manipulate caller's signal mask at this point.
-- All tasks in RTS will have All_Tasks_Mask initially.
- Result := pthread_create
- (T.Common.LL.Thread'Access,
- Attributes'Access,
- Thread_Body_Access (Wrapper),
- To_Address (T));
+ -- Note: the use of Unrestricted_Access in the following call is needed
+ -- because otherwise we have an error of getting a access-to-volatile
+ -- value which points to a non-volatile object. But in this case it is
+ -- safe to do this, since we know we have no problems with aliasing and
+ -- Unrestricted_Access bypasses this check.
+
+ Result :=
+ pthread_create
+ (T.Common.LL.Thread'Unrestricted_Access,
+ Attributes'Access,
+ Thread_Body_Access (Wrapper),
+ To_Address (T));
pragma Assert
(Result = 0 or else Result = EAGAIN or else Result = ENOMEM);
@@ -1081,9 +1076,7 @@ package body System.Task_Primitives.Operations is
----------------
procedure Initialize (S : in out Suspension_Object) is
- Mutex_Attr : aliased pthread_mutexattr_t;
- Cond_Attr : aliased pthread_condattr_t;
- Result : Interfaces.C.int;
+ Result : Interfaces.C.int;
begin
-- Initialize internal state (always to False (RM D.10(6)))
@@ -1093,10 +1086,7 @@ package body System.Task_Primitives.Operations is
-- Initialize internal mutex
- Result := pthread_mutexattr_init (Mutex_Attr'Access);
- pragma Assert (Result = 0);
-
- Result := pthread_mutex_init (S.L'Access, Mutex_Attr'Access);
+ Result := pthread_mutex_init (S.L'Access, null);
pragma Assert (Result = 0 or else Result = ENOMEM);
@@ -1106,10 +1096,7 @@ package body System.Task_Primitives.Operations is
-- Initialize internal condition variable
- Result := pthread_condattr_init (Cond_Attr'Access);
- pragma Assert (Result = 0);
-
- Result := pthread_cond_init (S.CV'Access, Cond_Attr'Access);
+ Result := pthread_cond_init (S.CV'Access, null);
pragma Assert (Result = 0 or else Result = ENOMEM);
diff --git a/gcc/ada/s-taprop-posix.adb b/gcc/ada/s-taprop-posix.adb
index 425508a32c2..667603b73b7 100644
--- a/gcc/ada/s-taprop-posix.adb
+++ b/gcc/ada/s-taprop-posix.adb
@@ -50,6 +50,7 @@ with Interfaces.C;
with System.Tasking.Debug;
with System.Interrupt_Management;
+with System.OS_Constants;
with System.OS_Primitives;
with System.Task_Info;
@@ -61,6 +62,7 @@ with System.Soft_Links;
package body System.Task_Primitives.Operations is
+ package OSC renames System.OS_Constants;
package SSL renames System.Soft_Links;
use System.Tasking.Debug;
@@ -171,6 +173,11 @@ package body System.Task_Primitives.Operations is
function To_Address is
new Ada.Unchecked_Conversion (Task_Id, System.Address);
+ function GNAT_pthread_condattr_setup
+ (attr : access pthread_condattr_t) return int;
+ pragma Import (C,
+ GNAT_pthread_condattr_setup, "__gnat_pthread_condattr_setup");
+
-------------------
-- Abort_Handler --
-------------------
@@ -666,7 +673,7 @@ package body System.Task_Primitives.Operations is
Result : Interfaces.C.int;
begin
Result := clock_gettime
- (clock_id => CLOCK_MONOTONIC, tp => TS'Unchecked_Access);
+ (clock_id => OSC.CLOCK_RT_Ada, tp => TS'Unchecked_Access);
pragma Assert (Result = 0);
return To_Duration (TS);
end Monotonic_Clock;
@@ -869,6 +876,9 @@ package body System.Task_Primitives.Operations is
pragma Assert (Result = 0 or else Result = ENOMEM);
if Result = 0 then
+ Result := GNAT_pthread_condattr_setup (Cond_Attr'Access);
+ pragma Assert (Result = 0);
+
Result :=
pthread_cond_init
(Self_ID.Common.LL.CV'Access, Cond_Attr'Access);
@@ -975,8 +985,14 @@ package body System.Task_Primitives.Operations is
-- do not need to manipulate caller's signal mask at this point.
-- All tasks in RTS will have All_Tasks_Mask initially.
+ -- Note: the use of Unrestricted_Access in the following call is needed
+ -- because otherwise we have an error of getting a access-to-volatile
+ -- value which points to a non-volatile object. But in this case it is
+ -- safe to do this, since we know we have no problems with aliasing and
+ -- Unrestricted_Access bypasses this check.
+
Result := pthread_create
- (T.Common.LL.Thread'Access,
+ (T.Common.LL.Thread'Unrestricted_Access,
Attributes'Access,
Thread_Body_Access (Wrapper),
To_Address (T));
@@ -1093,6 +1109,10 @@ package body System.Task_Primitives.Operations is
-- underlying OS entities fails.
raise Storage_Error;
+
+ else
+ Result := GNAT_pthread_condattr_setup (Cond_Attr'Access);
+ pragma Assert (Result = 0);
end if;
Result := pthread_cond_init (S.CV'Access, Cond_Attr'Access);
diff --git a/gcc/ada/s-taprop-solaris.adb b/gcc/ada/s-taprop-solaris.adb
index b5fe1ee9d42..92088e10cb4 100644
--- a/gcc/ada/s-taprop-solaris.adb
+++ b/gcc/ada/s-taprop-solaris.adb
@@ -43,6 +43,7 @@ with Interfaces.C;
with System.Multiprocessors;
with System.Tasking.Debug;
with System.Interrupt_Management;
+with System.OS_Constants;
with System.OS_Primitives;
with System.Task_Info;
@@ -58,6 +59,7 @@ with System.Soft_Links;
package body System.Task_Primitives.Operations is
+ package OSC renames System.OS_Constants;
package SSL renames System.Soft_Links;
use System.Tasking.Debug;
@@ -773,7 +775,7 @@ package body System.Task_Primitives.Operations is
TS : aliased timespec;
Result : Interfaces.C.int;
begin
- Result := clock_gettime (CLOCK_REALTIME, TS'Unchecked_Access);
+ Result := clock_gettime (OSC.CLOCK_RT_Ada, TS'Unchecked_Access);
pragma Assert (Result = 0);
return To_Duration (TS);
end Monotonic_Clock;
@@ -1005,6 +1007,12 @@ package body System.Task_Primitives.Operations is
Opts := THR_DETACHED + THR_BOUND;
end if;
+ -- Note: the use of Unrestricted_Access in the following call is needed
+ -- because otherwise we have an error of getting a access-to-volatile
+ -- value which points to a non-volatile object. But in this case it is
+ -- safe to do this, since we know we have no problems with aliasing and
+ -- Unrestricted_Access bypasses this check.
+
Result :=
thr_create
(System.Null_Address,
@@ -1012,7 +1020,7 @@ package body System.Task_Primitives.Operations is
Thread_Body_Access (Wrapper),
To_Address (T),
Opts,
- T.Common.LL.Thread'Access);
+ T.Common.LL.Thread'Unrestricted_Access);
Succeeded := Result = 0;
pragma Assert
diff --git a/gcc/ada/s-taprop-tru64.adb b/gcc/ada/s-taprop-tru64.adb
index b0b727d9bb1..8d69e5b19b1 100644
--- a/gcc/ada/s-taprop-tru64.adb
+++ b/gcc/ada/s-taprop-tru64.adb
@@ -43,6 +43,7 @@ with Interfaces.C;
with System.Tasking.Debug;
with System.Interrupt_Management;
+with System.OS_Constants;
with System.OS_Primitives;
with System.Task_Info;
@@ -54,6 +55,7 @@ with System.Soft_Links;
package body System.Task_Primitives.Operations is
+ package OSC renames System.OS_Constants;
package SSL renames System.Soft_Links;
use System.Tasking.Debug;
@@ -589,7 +591,7 @@ package body System.Task_Primitives.Operations is
TS : aliased timespec;
Result : Interfaces.C.int;
begin
- Result := clock_gettime (CLOCK_REALTIME, TS'Unchecked_Access);
+ Result := clock_gettime (OSC.CLOCK_RT_Ada, TS'Unchecked_Access);
pragma Assert (Result = 0);
return To_Duration (TS);
end Monotonic_Clock;
@@ -887,9 +889,15 @@ package body System.Task_Primitives.Operations is
-- do not need to manipulate caller's signal mask at this point.
-- All tasks in RTS will have All_Tasks_Mask initially.
+ -- Note: the use of Unrestricted_Access in the following call is needed
+ -- because otherwise we have an error of getting a access-to-volatile
+ -- value which points to a non-volatile object. But in this case it is
+ -- safe to do this, since we know we have no problems with aliasing and
+ -- Unrestricted_Access bypasses this check.
+
Result :=
pthread_create
- (T.Common.LL.Thread'Access,
+ (T.Common.LL.Thread'Unrestricted_Access,
Attributes'Access,
Thread_Body_Access (Wrapper),
To_Address (T));
diff --git a/gcc/ada/s-taprop-vms.adb b/gcc/ada/s-taprop-vms.adb
index 92b6023bdff..67cf363dd4e 100644
--- a/gcc/ada/s-taprop-vms.adb
+++ b/gcc/ada/s-taprop-vms.adb
@@ -809,9 +809,15 @@ package body System.Task_Primitives.Operations is
(Attributes'Access, PTHREAD_EXPLICIT_SCHED);
pragma Assert (Result = 0);
+ -- Note: the use of Unrestricted_Access in the following call is needed
+ -- because otherwise we have an error of getting a access-to-volatile
+ -- value which points to a non-volatile object. But in this case it is
+ -- safe to do this, since we know we have no problems with aliasing and
+ -- Unrestricted_Access bypasses this check.
+
Result :=
pthread_create
- (T.Common.LL.Thread'Access,
+ (T.Common.LL.Thread'Unrestricted_Access,
Attributes'Access,
Thread_Body_Access (Wrapper),
To_Address (T));
diff --git a/gcc/ada/s-taprop-vxworks.adb b/gcc/ada/s-taprop-vxworks.adb
index be76162b284..eec3a9da10d 100644
--- a/gcc/ada/s-taprop-vxworks.adb
+++ b/gcc/ada/s-taprop-vxworks.adb
@@ -46,6 +46,7 @@ with System.Multiprocessors;
with System.Tasking.Debug;
with System.Interrupt_Management;
with System.Float_Control;
+with System.OS_Constants;
with System.Soft_Links;
-- We use System.Soft_Links instead of System.Tasking.Initialization
@@ -58,6 +59,7 @@ with System.VxWorks.Ext;
package body System.Task_Primitives.Operations is
+ package OSC renames System.OS_Constants;
package SSL renames System.Soft_Links;
use System.Tasking.Debug;
@@ -718,7 +720,7 @@ package body System.Task_Primitives.Operations is
TS : aliased timespec;
Result : int;
begin
- Result := clock_gettime (CLOCK_REALTIME, TS'Unchecked_Access);
+ Result := clock_gettime (OSC.CLOCK_RT_Ada, TS'Unchecked_Access);
pragma Assert (Result = 0);
return To_Duration (TS);
end Monotonic_Clock;
diff --git a/gcc/ada/s-utf_32.adb b/gcc/ada/s-utf_32.adb
index a5af4fbc60e..f044b9bcc70 100755
--- a/gcc/ada/s-utf_32.adb
+++ b/gcc/ada/s-utf_32.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2005-2010, Free Software Foundation, Inc. --
+-- Copyright (C) 2005-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- --
@@ -6182,6 +6182,7 @@ package body System.UTF_32 is
function Is_UTF_32_Line_Terminator (U : UTF_32) return Boolean is
begin
return U in 10 .. 13 -- Ascii.LF Ascii.VT Ascii.FF Ascii.CR
+ or else U = 16#00085# -- NEL
or else U = 16#02028# -- LINE SEPARATOR
or else U = 16#02029#; -- PARAGRAPH SEPARATOR
end Is_UTF_32_Line_Terminator;
diff --git a/gcc/ada/sem.adb b/gcc/ada/sem.adb
index b463d37a938..2a273609a09 100644
--- a/gcc/ada/sem.adb
+++ b/gcc/ada/sem.adb
@@ -35,6 +35,7 @@ with Lib; use Lib;
with Lib.Load; use Lib.Load;
with Nlists; use Nlists;
with Output; use Output;
+with Restrict; use Restrict;
with Sem_Attr; use Sem_Attr;
with Sem_Ch2; use Sem_Ch2;
with Sem_Ch3; use Sem_Ch3;
@@ -1361,6 +1362,11 @@ package body Sem is
-- Variable used to save values of config switches while we analyze the
-- new unit, to be restored on exit for proper recursive behavior.
+ Save_Cunit_Restrictions : Save_Cunit_Boolean_Restrictions;
+ -- Used to save non-partition wide restrictions before processing new
+ -- unit. All with'ed units are analyzed with config restrictions reset
+ -- and we need to restore these saved values at the end.
+
procedure Do_Analyze;
-- Procedure to analyze the compilation unit. This is called more than
-- once when the high level optimizer is activated.
@@ -1442,11 +1448,27 @@ package body Sem is
In_Spec_Expression := False;
Set_Comes_From_Source_Default (False);
+
+ -- Save current config switches and reset then appropriately
+
Save_Opt_Config_Switches (Save_Config_Switches);
Set_Opt_Config_Switches
(Is_Internal_File_Name (Unit_File_Name (Current_Sem_Unit)),
Current_Sem_Unit = Main_Unit);
+ -- Save current non-partition-wide restrictions
+
+ Save_Cunit_Restrictions := Cunit_Boolean_Restrictions_Save;
+
+ -- For unit in main extended unit, we reset the configuration values
+ -- for the non-partition-wide restrictions. For other units reset them.
+
+ if In_Extended_Main_Source_Unit (Comp_Unit) then
+ Restore_Config_Cunit_Boolean_Restrictions;
+ else
+ Reset_Cunit_Boolean_Restrictions;
+ end if;
+
-- Only do analysis of unit that has not already been analyzed
if not Analyzed (Comp_Unit) then
@@ -1511,6 +1533,11 @@ package body Sem is
Outer_Generic_Scope := S_Outer_Gen_Scope;
Restore_Opt_Config_Switches (Save_Config_Switches);
+
+ -- Deal with restore of restrictions
+
+ Cunit_Boolean_Restrictions_Restore (Save_Cunit_Restrictions);
+
Expander_Mode_Restore;
if Debug_Unit_Walk then
diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index ae7edbf9dc2..c2277851bc4 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -841,13 +841,8 @@ package body Sem_Attr is
and then not In_Instance
and then not In_Inlined_Body
then
- if Restriction_Check_Required (No_Implicit_Aliasing) then
- Error_Attr_P
- ("prefix of % attribute must be explicitly aliased");
- else
- Error_Attr_P
- ("prefix of % attribute must be aliased");
- end if;
+ Error_Attr_P ("prefix of % attribute must be aliased");
+ Check_No_Implicit_Aliasing (P);
end if;
end Analyze_Access_Attribute;
@@ -2245,6 +2240,8 @@ package body Sem_Attr is
if Restriction_Check_Required (No_Implicit_Aliasing) then
if not Is_Aliased_View (P) then
Check_Restriction (No_Implicit_Aliasing, P);
+ else
+ Check_No_Implicit_Aliasing (P);
end if;
end if;
@@ -7824,14 +7821,30 @@ package body Sem_Attr is
T := T / 10;
end loop;
+ -- User declared enum type with discard names
+
+ elsif Discard_Names (R) then
+
+ -- If range is null, result is zero, that has already
+ -- been dealt with, so what we need is the power of ten
+ -- that accomodates the Pos of the largest value, which
+ -- is the high bound of the range + one for the space.
+
+ W := 1;
+ T := Hi;
+ while T /= 0 loop
+ T := T / 10;
+ W := W + 1;
+ end loop;
+
-- Only remaining possibility is user declared enum type
+ -- with normal case of Discard_Names not active.
else
pragma Assert (Is_Enumeration_Type (P_Type));
W := 0;
L := First_Literal (P_Type);
-
while Present (L) loop
-- Only pay attention to in range characters
@@ -8645,13 +8658,14 @@ package body Sem_Attr is
end if;
end if;
- -- Check the static accessibility rule of 3.10.2(28).
- -- Note that this check is not performed for the
- -- case of an anonymous access type, since the access
- -- attribute is always legal in such a context.
+ -- Check the static accessibility rule of 3.10.2(28). Note that
+ -- this check is not performed for the case of an anonymous
+ -- access type, since the access attribute is always legal
+ -- in such a context.
if Attr_Id /= Attribute_Unchecked_Access
- and then Object_Access_Level (P) > Type_Access_Level (Btyp)
+ and then
+ Object_Access_Level (P) > Deepest_Type_Access_Level (Btyp)
and then Ekind (Btyp) = E_General_Access_Type
then
Accessibility_Message;
@@ -8673,7 +8687,7 @@ package body Sem_Attr is
-- anonymous_access_to_protected, there are no accessibility
-- checks either. Omit check entirely for Unrestricted_Access.
- elsif Object_Access_Level (P) > Type_Access_Level (Btyp)
+ elsif Object_Access_Level (P) > Deepest_Type_Access_Level (Btyp)
and then Comes_From_Source (N)
and then Ekind (Btyp) = E_Access_Protected_Subprogram_Type
and then Attr_Id /= Attribute_Unrestricted_Access
diff --git a/gcc/ada/sem_ch10.adb b/gcc/ada/sem_ch10.adb
index 34346e39925..e5afc1b8b2f 100644
--- a/gcc/ada/sem_ch10.adb
+++ b/gcc/ada/sem_ch10.adb
@@ -467,7 +467,6 @@ package body Sem_Ch10 is
-- generated with clauses or limited with clauses. Note that
-- we examine with clauses having pragmas Elaborate or
-- Elaborate_All applied to them due to cases such as:
- --
-- with Pack;
-- with Pack;
@@ -725,7 +724,12 @@ package body Sem_Ch10 is
return;
else
+ -- Analyze the package spec
+
Semantics (Lib_Unit);
+
+ -- Check for unused with's
+
Check_Unused_Withs (Get_Cunit_Unit_Number (Lib_Unit));
-- Verify that the library unit is a package declaration
@@ -857,8 +861,6 @@ package body Sem_Ch10 is
declare
Save_Style_Check : constant Boolean := Style_Check;
- Save_C_Restrict : constant Save_Cunit_Boolean_Restrictions :=
- Cunit_Boolean_Restrictions_Save;
begin
if not GNAT_Mode then
@@ -867,8 +869,10 @@ package body Sem_Ch10 is
Semantics (Parent_Spec (Unit_Node));
Version_Update (N, Parent_Spec (Unit_Node));
+
+ -- Restore style check settings
+
Style_Check := Save_Style_Check;
- Cunit_Boolean_Restrictions_Restore (Save_C_Restrict);
end;
end if;
@@ -1052,8 +1056,6 @@ package body Sem_Ch10 is
Un : Unit_Number_Type;
Save_Style_Check : constant Boolean := Style_Check;
- Save_C_Restrict : constant Save_Cunit_Boolean_Restrictions :=
- Cunit_Boolean_Restrictions_Save;
begin
Item := First (Context_Items (N));
@@ -1122,8 +1124,9 @@ package body Sem_Ch10 is
Next (Item);
end loop;
+ -- Restore style checks settings
+
Style_Check := Save_Style_Check;
- Cunit_Boolean_Restrictions_Restore (Save_C_Restrict);
end;
end if;
@@ -1641,7 +1644,7 @@ package body Sem_Ch10 is
-- subunit, and that the current unit is one of its parents which was
-- being analyzed to provide the needed context for the analysis of the
-- subunit. In this case we analyze the subunit and continue with the
- -- parent, without looking a subsequent subunits.
+ -- parent, without looking at subsequent subunits.
if Is_Loaded (Subunit_Name) then
@@ -2351,7 +2354,6 @@ package body Sem_Ch10 is
-- warnings if we have this definite error.
Save_Style_Check : constant Boolean := Opt.Style_Check;
- Save_C_Restrict : Save_Cunit_Boolean_Restrictions;
begin
U := Unit (Library_Unit (N));
@@ -2388,10 +2390,6 @@ package body Sem_Ch10 is
end if;
end if;
- -- Save current restriction set, does not apply to with'ed unit
-
- Save_C_Restrict := Cunit_Boolean_Restrictions_Save;
-
-- Several actions are skipped for dummy packages (those supplied for
-- with's where no matching file could be found). Such packages are
-- identified by the Sloc value being set to No_Location.
@@ -2591,10 +2589,9 @@ package body Sem_Ch10 is
end if;
end if;
- -- Restore style checks and restrictions
+ -- Restore style checks
Style_Check := Save_Style_Check;
- Cunit_Boolean_Restrictions_Restore (Save_C_Restrict);
-- Record the reference, but do NOT set the unit as referenced, we want
-- to consider the unit as unreferenced if this is the only reference
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb
index e51b8029803..2a431f8635e 100644
--- a/gcc/ada/sem_ch12.adb
+++ b/gcc/ada/sem_ch12.adb
@@ -5076,6 +5076,18 @@ package body Sem_Ch12 is
then
null;
+ -- If the formal package has an "others" box association that
+ -- covers this formal, there is no need for a check either.
+
+ elsif Nkind (Unit_Declaration_Node (E2)) in
+ N_Formal_Subprogram_Declaration
+ and then Box_Present (Unit_Declaration_Node (E2))
+ then
+ null;
+
+ -- Otherwise the actual in the formal and the actual in the
+ -- instantiation of the formal must match, up to renamings.
+
else
Check_Mismatch
(Ekind (E2) /= Ekind (E1) or else (Alias (E1)) /= Alias (E2));
@@ -12383,9 +12395,11 @@ package body Sem_Ch12 is
procedure Reset_Entity (N : Node_Id) is
procedure Set_Global_Type (N : Node_Id; N2 : Node_Id);
- -- If the type of N2 is global to the generic unit. Save the type in
- -- the generic node.
- -- What does this comment mean???
+ -- If the type of N2 is global to the generic unit, save the type in
+ -- the generic node. Just as we perform name capture for explicit
+ -- references within the generic, we must capture the global types
+ -- of local entities because they may participate in resolution in
+ -- the instance.
function Top_Ancestor (E : Entity_Id) return Entity_Id;
-- Find the ultimate ancestor of the current unit. If it is not a
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index acfb989dc3c..7de3c164ede 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -161,15 +161,15 @@ package body Sem_Ch13 is
----------------------------------------------
-- The following table collects unchecked conversions for validation.
- -- Entries are made by Validate_Unchecked_Conversion and then the
- -- call to Validate_Unchecked_Conversions does the actual error
- -- checking and posting of warnings. The reason for this delayed
- -- processing is to take advantage of back-annotations of size and
- -- alignment values performed by the back end.
+ -- Entries are made by Validate_Unchecked_Conversion and then the call
+ -- to Validate_Unchecked_Conversions does the actual error checking and
+ -- posting of warnings. The reason for this delayed processing is to take
+ -- advantage of back-annotations of size and alignment values performed by
+ -- the back end.
- -- Note: the reason we store a Source_Ptr value instead of a Node_Id
- -- is that by the time Validate_Unchecked_Conversions is called, Sprint
- -- will already have modified all Sloc values if the -gnatD option is set.
+ -- Note: the reason we store a Source_Ptr value instead of a Node_Id is
+ -- that by the time Validate_Unchecked_Conversions is called, Sprint will
+ -- already have modified all Sloc values if the -gnatD option is set.
type UC_Entry is record
Eloc : Source_Ptr; -- node used for posting warnings
@@ -193,13 +193,13 @@ package body Sem_Ch13 is
-- for X'Address use Expr
- -- where Expr is of the form Y'Address or recursively is a reference
- -- to a constant of either of these forms, and X and Y are entities of
- -- objects, then if Y has a smaller alignment than X, that merits a
- -- warning about possible bad alignment. The following table collects
- -- address clauses of this kind. We put these in a table so that they
- -- can be checked after the back end has completed annotation of the
- -- alignments of objects, since we can catch more cases that way.
+ -- where Expr is of the form Y'Address or recursively is a reference to a
+ -- constant of either of these forms, and X and Y are entities of objects,
+ -- then if Y has a smaller alignment than X, that merits a warning about
+ -- possible bad alignment. The following table collects address clauses of
+ -- this kind. We put these in a table so that they can be checked after the
+ -- back end has completed annotation of the alignments of objects, since we
+ -- can catch more cases that way.
type Address_Clause_Check_Record is record
N : Node_Id;
@@ -728,8 +728,9 @@ package body Sem_Ch13 is
A_Id : constant Aspect_Id := Get_Aspect_Id (Nam);
Anod : Node_Id;
- Eloc : Source_Ptr := Sloc (Expr);
- -- Source location of expression, modified when we split PPC's
+ Eloc : Source_Ptr := No_Location;
+ -- Source location of expression, modified when we split PPC's. It
+ -- is set below when Expr is present.
procedure Check_False_Aspect_For_Derived_Type;
-- This procedure checks for the case of a false aspect for a
@@ -804,6 +805,18 @@ package body Sem_Ch13 is
goto Continue;
end if;
+ -- Set the source location of expression, used in the case of
+ -- a failed precondition/postcondition or invariant. Note that
+ -- the source location of the expression is not usually the best
+ -- choice here. For example, it gets located on the last AND
+ -- keyword in a chain of boolean expressiond AND'ed together.
+ -- It is best to put the message on the first character of the
+ -- assertion, which is the effect of the First_Node call here.
+
+ if Present (Expr) then
+ Eloc := Sloc (First_Node (Expr));
+ end if;
+
-- Check restriction No_Implementation_Aspect_Specifications
if Impl_Defined_Aspects (A_Id) then
@@ -8605,8 +8618,8 @@ package body Sem_Ch13 is
Target := Ancestor_Subtype (Etype (Act_Unit));
-- If either type is generic, the instantiation happens within a generic
- -- unit, and there is nothing to check. The proper check
- -- will happen when the enclosing generic is instantiated.
+ -- unit, and there is nothing to check. The proper check will happen
+ -- when the enclosing generic is instantiated.
if Is_Generic_Type (Source) or else Is_Generic_Type (Target) then
return;
@@ -8704,9 +8717,8 @@ package body Sem_Ch13 is
end if;
-- If unchecked conversion to access type, and access type is declared
- -- in the same unit as the unchecked conversion, then set the
- -- No_Strict_Aliasing flag (no strict aliasing is implicit in this
- -- situation).
+ -- in the same unit as the unchecked conversion, then set the flag
+ -- No_Strict_Aliasing (no strict aliasing is implicit here)
if Is_Access_Type (Target) and then
In_Same_Source_Unit (Target, N)
@@ -8714,11 +8726,11 @@ package body Sem_Ch13 is
Set_No_Strict_Aliasing (Implementation_Base_Type (Target));
end if;
- -- Generate N_Validate_Unchecked_Conversion node for back end in
- -- case the back end needs to perform special validation checks.
+ -- Generate N_Validate_Unchecked_Conversion node for back end in case
+ -- the back end needs to perform special validation checks.
- -- Shouldn't this be in Exp_Ch13, since the check only gets done
- -- if we have full expansion and the back end is called ???
+ -- Shouldn't this be in Exp_Ch13, since the check only gets done if we
+ -- have full expansion and the back end is called ???
Vnode :=
Make_Validate_Unchecked_Conversion (Sloc (N));
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index 488e6dc98cc..5cc06e7d899 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -726,13 +726,33 @@ package body Sem_Ch3 is
-- If the access definition is the return type of another access to
-- function, scope is the current one, because it is the one of the
- -- current type declaration.
+ -- current type declaration, except for the pathological case below.
if Nkind_In (Related_Nod, N_Object_Declaration,
N_Access_Function_Definition)
then
Anon_Scope := Current_Scope;
+ -- A pathological case: function returning access functions that
+ -- return access functions, etc. Each anonymous access type created
+ -- is in the enclosing scope of the outermost function.
+
+ declare
+ Par : Node_Id;
+
+ begin
+ Par := Related_Nod;
+ while Nkind_In (Par, N_Access_Function_Definition,
+ N_Access_Definition)
+ loop
+ Par := Parent (Par);
+ end loop;
+
+ if Nkind (Par) = N_Function_Specification then
+ Anon_Scope := Scope (Defining_Entity (Par));
+ end if;
+ end;
+
-- For the anonymous function result case, retrieve the scope of the
-- function specification's associated entity rather than using the
-- current scope. The current scope will be the function itself if the
@@ -1876,7 +1896,9 @@ package body Sem_Ch3 is
-- (Ada 2005: AI-230): Accessibility check for anonymous
-- components
- if Type_Access_Level (Etype (E)) > Type_Access_Level (T) then
+ if Type_Access_Level (Etype (E)) >
+ Deepest_Type_Access_Level (T)
+ then
Error_Msg_N
("expression has deeper access level than component " &
"(RM 3.10.2 (12.2))", E);
@@ -2664,8 +2686,8 @@ package body Sem_Ch3 is
-- Process expression, replacing error by integer zero, to avoid
-- cascaded errors or aborts further along in the processing
- -- Replace Error by integer zero, which seems least likely to
- -- cause cascaded errors.
+ -- Replace Error by integer zero, which seems least likely to cause
+ -- cascaded errors.
if E = Error then
Rewrite (E, Make_Integer_Literal (Sloc (E), Uint_0));
@@ -4042,6 +4064,19 @@ package body Sem_Ch3 is
T := Process_Subtype (Subtype_Indication (N), N, Id, 'P');
+ -- Class-wide equivalent types of records with unknown discriminants
+ -- involve the generation of an itype which serves as the private view
+ -- of a constrained record subtype. In such cases the base type of the
+ -- current subtype we are processing is the private itype. Use the full
+ -- of the private itype when decorating various attributes.
+
+ if Is_Itype (T)
+ and then Is_Private_Type (T)
+ and then Present (Full_View (T))
+ then
+ T := Full_View (T);
+ end if;
+
-- Inherit common attributes
Set_Is_Generic_Type (Id, Is_Generic_Type (Base_Type (T)));
@@ -11764,6 +11799,11 @@ package body Sem_Ch3 is
-- needed, since checks may cause duplication of the expressions
-- which must not be reevaluated.
+ -- The forced evaluation removes side effects from expressions,
+ -- which should occur also in Alfa mode. Otherwise, we end up with
+ -- unexpected insertions of actions at places where this is not
+ -- supposed to occur, e.g. on default parameters of a call.
+
if Expander_Active then
Force_Evaluation (Low_Bound (R));
Force_Evaluation (High_Bound (R));
@@ -18304,6 +18344,11 @@ package body Sem_Ch3 is
-- if needed, before applying checks, since checks may cause
-- duplication of the expression without forcing evaluation.
+ -- The forced evaluation removes side effects from expressions,
+ -- which should occur also in Alfa mode. Otherwise, we end up with
+ -- unexpected insertions of actions at places where this is not
+ -- supposed to occur, e.g. on default parameters of a call.
+
if Expander_Active then
Force_Evaluation (Lo);
Force_Evaluation (Hi);
@@ -18414,6 +18459,11 @@ package body Sem_Ch3 is
-- Case of other than an explicit N_Range node
+ -- The forced evaluation removes side effects from expressions, which
+ -- should occur also in Alfa mode. Otherwise, we end up with unexpected
+ -- insertions of actions at places where this is not supposed to occur,
+ -- e.g. on default parameters of a call.
+
elsif Expander_Active then
Get_Index_Bounds (R, Lo, Hi);
Force_Evaluation (Lo);
diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb
index 4b438e13f1c..0f918c06b4c 100644
--- a/gcc/ada/sem_ch4.adb
+++ b/gcc/ada/sem_ch4.adb
@@ -3432,8 +3432,8 @@ package body Sem_Ch4 is
-- of the high bound.
procedure Check_Universal_Expression (N : Node_Id);
- -- In Ada83, reject bounds of a universal range that are not literals or
- -- entity names.
+ -- In Ada 83, reject bounds of a universal range that are not literals
+ -- or entity names.
-----------------------
-- Check_Common_Type --
diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb
index 0e6c5cf98bd..073bc2b840a 100644
--- a/gcc/ada/sem_ch5.adb
+++ b/gcc/ada/sem_ch5.adb
@@ -75,6 +75,14 @@ package body Sem_Ch5 is
-- messages. This variable is recursively saved on entry to processing the
-- construct, and restored on exit.
+ procedure Pre_Analyze_Range (R_Copy : Node_Id);
+ -- Determine expected type of range or domain of iteration of Ada 2012
+ -- loop by analyzing separate copy. Do the analysis and resolution of the
+ -- copy of the bound(s) with expansion disabled, to prevent the generation
+ -- of finalization actions. This prevents memory leaks when the bounds
+ -- contain calls to functions returning controlled arrays or when the
+ -- domain of iteration is a container.
+
------------------------
-- Analyze_Assignment --
------------------------
@@ -1618,90 +1626,6 @@ package body Sem_Ch5 is
-- calls that use the secondary stack, returning True if any such call
-- is found, and False otherwise.
- procedure Pre_Analyze_Range (R_Copy : Node_Id);
- -- Determine expected type of range or domain of iteration of Ada 2012
- -- loop by analyzing separate copy. Do the analysis and resolution of
- -- the copy of the bound(s) with expansion disabled, to prevent the
- -- generation of finalization actions. This prevents memory leaks when
- -- the bounds contain calls to functions returning controlled arrays or
- -- when the domain of iteration is a container.
-
- -----------------------
- -- Pre_Analyze_Range --
- -----------------------
-
- procedure Pre_Analyze_Range (R_Copy : Node_Id) is
- Save_Analysis : Boolean;
- begin
- Save_Analysis := Full_Analysis;
- Full_Analysis := False;
- Expander_Mode_Save_And_Set (False);
-
- Analyze (R_Copy);
-
- if Nkind (R_Copy) in N_Subexpr
- and then Is_Overloaded (R_Copy)
- then
-
- -- Apply preference rules for range of predefined integer types,
- -- or diagnose true ambiguity.
-
- declare
- I : Interp_Index;
- It : Interp;
- Found : Entity_Id := Empty;
-
- begin
- Get_First_Interp (R_Copy, I, It);
- while Present (It.Typ) loop
- if Is_Discrete_Type (It.Typ) then
- if No (Found) then
- Found := It.Typ;
- else
- if Scope (Found) = Standard_Standard then
- null;
-
- elsif Scope (It.Typ) = Standard_Standard then
- Found := It.Typ;
-
- else
- -- Both of them are user-defined
-
- Error_Msg_N
- ("ambiguous bounds in range of iteration",
- R_Copy);
- Error_Msg_N ("\possible interpretations:", R_Copy);
- Error_Msg_NE ("\\} ", R_Copy, Found);
- Error_Msg_NE ("\\} ", R_Copy, It.Typ);
- exit;
- end if;
- end if;
- end if;
-
- Get_Next_Interp (I, It);
- end loop;
- end;
- end if;
-
- if Is_Entity_Name (R_Copy)
- and then Is_Type (Entity (R_Copy))
- then
-
- -- Subtype mark in iteration scheme
-
- null;
-
- elsif Nkind (R_Copy) in N_Subexpr then
-
- -- Expression in range, or Ada 2012 iterator
-
- Resolve (R_Copy);
- end if;
-
- Expander_Mode_Restore;
- Full_Analysis := Save_Analysis;
- end Pre_Analyze_Range;
-
--------------------
-- Process_Bounds --
--------------------
@@ -1855,7 +1779,7 @@ package body Sem_Ch5 is
if New_Lo_Bound /= Lo
and then Is_Static_Expression (New_Lo_Bound)
then
- Rewrite (Low_Bound (R), New_Copy (New_Lo_Bound));
+ Rewrite (Low_Bound (R), New_Copy (New_Lo_Bound));
end if;
if New_Hi_Bound /= Hi
@@ -2034,7 +1958,7 @@ package body Sem_Ch5 is
begin
if Present (H)
and then Enclosing_Dynamic_Scope (H) =
- Enclosing_Dynamic_Scope (Id)
+ Enclosing_Dynamic_Scope (Id)
and then Ekind (H) = E_Variable
and then Is_Discrete_Type (Etype (H))
then
@@ -2059,7 +1983,7 @@ package body Sem_Ch5 is
then
Process_Bounds (DS);
- -- expander not active or else range of iteration is a subtype
+ -- Expander not active or else range of iteration is a subtype
-- indication, an entity, or a function call that yields an
-- aggregate or a container.
@@ -2513,12 +2437,95 @@ package body Sem_Ch5 is
----------------------------
procedure Analyze_Loop_Statement (N : Node_Id) is
- Loop_Statement : constant Node_Id := N;
- Id : constant Node_Id := Identifier (Loop_Statement);
- Iter : constant Node_Id := Iteration_Scheme (Loop_Statement);
+ function Is_Container_Iterator (Iter : Node_Id) return Boolean;
+ -- Given a loop iteration scheme, determine whether it is an Ada 2012
+ -- container iteration.
+
+ function Is_Wrapped_In_Block (N : Node_Id) return Boolean;
+ -- Determine whether node N is the sole statement of a block
+
+ ---------------------------
+ -- Is_Container_Iterator --
+ ---------------------------
+
+ function Is_Container_Iterator (Iter : Node_Id) return Boolean is
+ begin
+ -- Infinite loop
+
+ if No (Iter) then
+ return False;
+
+ -- While loop
+
+ elsif Present (Condition (Iter)) then
+ return False;
+
+ -- for Def_Id in [reverse] Name loop
+ -- for Def_Id [: Subtype_Indication] of [reverse] Name loop
+
+ elsif Present (Iterator_Specification (Iter)) then
+ declare
+ Nam : constant Node_Id := Name (Iterator_Specification (Iter));
+ Nam_Copy : Node_Id;
+
+ begin
+ Nam_Copy := New_Copy_Tree (Nam);
+ Set_Parent (Nam_Copy, Parent (Nam));
+ Pre_Analyze_Range (Nam_Copy);
+
+ -- The only two options here are iteration over a container or
+ -- an array.
+
+ return not Is_Array_Type (Etype (Nam_Copy));
+ end;
+
+ -- for Def_Id in [reverse] Discrete_Subtype_Definition loop
+
+ else
+ declare
+ LP : constant Node_Id := Loop_Parameter_Specification (Iter);
+ DS : constant Node_Id := Discrete_Subtype_Definition (LP);
+ DS_Copy : Node_Id;
+
+ begin
+ DS_Copy := New_Copy_Tree (DS);
+ Set_Parent (DS_Copy, Parent (DS));
+ Pre_Analyze_Range (DS_Copy);
+
+ -- Check for a call to Iterate ()
+
+ return
+ Nkind (DS_Copy) = N_Function_Call
+ and then Needs_Finalization (Etype (DS_Copy));
+ end;
+ end if;
+ end Is_Container_Iterator;
+
+ -------------------------
+ -- Is_Wrapped_In_Block --
+ -------------------------
+
+ function Is_Wrapped_In_Block (N : Node_Id) return Boolean is
+ HSS : constant Node_Id := Parent (N);
+
+ begin
+ return
+ Nkind (HSS) = N_Handled_Sequence_Of_Statements
+ and then Nkind (Parent (HSS)) = N_Block_Statement
+ and then First (Statements (HSS)) = N
+ and then No (Next (First (Statements (HSS))));
+ end Is_Wrapped_In_Block;
+
+ -- Local declarations
+
+ Id : constant Node_Id := Identifier (N);
+ Iter : constant Node_Id := Iteration_Scheme (N);
+ Loc : constant Source_Ptr := Sloc (N);
Ent : Entity_Id;
+ -- Start of processing for Analyze_Loop_Statement
+
begin
if Present (Id) then
@@ -2534,15 +2541,13 @@ package body Sem_Ch5 is
if No (Ent) then
if Total_Errors_Detected /= 0 then
- Ent :=
- New_Internal_Entity
- (E_Loop, Current_Scope, Sloc (Loop_Statement), 'L');
+ Ent := New_Internal_Entity (E_Loop, Current_Scope, Loc, 'L');
else
raise Program_Error;
end if;
else
- Generate_Reference (Ent, Loop_Statement, ' ');
+ Generate_Reference (Ent, N, ' ');
Generate_Definition (Ent);
-- If we found a label, mark its type. If not, ignore it, since it
@@ -2555,7 +2560,7 @@ package body Sem_Ch5 is
Set_Ekind (Ent, E_Loop);
if Nkind (Parent (Ent)) = N_Implicit_Label_Declaration then
- Set_Label_Construct (Parent (Ent), Loop_Statement);
+ Set_Label_Construct (Parent (Ent), N);
end if;
end if;
end if;
@@ -2563,11 +2568,28 @@ package body Sem_Ch5 is
-- Case of no identifier present
else
- Ent :=
- New_Internal_Entity
- (E_Loop, Current_Scope, Sloc (Loop_Statement), 'L');
- Set_Etype (Ent, Standard_Void_Type);
- Set_Parent (Ent, Loop_Statement);
+ Ent := New_Internal_Entity (E_Loop, Current_Scope, Loc, 'L');
+ Set_Etype (Ent, Standard_Void_Type);
+ Set_Parent (Ent, N);
+ end if;
+
+ -- Iteration over a container in Ada 2012 involves the creation of a
+ -- controlled iterator object. Wrap the loop in a block to ensure the
+ -- timely finalization of the iterator and release of container locks.
+
+ if Ada_Version >= Ada_2012
+ and then Is_Container_Iterator (Iter)
+ and then not Is_Wrapped_In_Block (N)
+ then
+ Rewrite (N,
+ Make_Block_Statement (Loc,
+ Declarations => New_List,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Relocate_Node (N)))));
+
+ Analyze (N);
+ return;
end if;
-- Kill current values on entry to loop, since statements in the body of
@@ -2610,7 +2632,7 @@ package body Sem_Ch5 is
end;
end if;
- Analyze_Statements (Statements (Loop_Statement));
+ Analyze_Statements (Statements (N));
end if;
-- Finish up processing for the loop. We kill all current values, since
@@ -2619,7 +2641,7 @@ package body Sem_Ch5 is
-- know will execute at least once, but it's not worth the trouble and
-- the front end is not in the business of flow tracing.
- Process_End_Label (Loop_Statement, 'e', Ent);
+ Process_End_Label (N, 'e', Ent);
End_Scope;
Kill_Current_Values;
@@ -2871,4 +2893,76 @@ package body Sem_Ch5 is
end if;
end Check_Unreachable_Code;
+ -----------------------
+ -- Pre_Analyze_Range --
+ -----------------------
+
+ procedure Pre_Analyze_Range (R_Copy : Node_Id) is
+ Save_Analysis : constant Boolean := Full_Analysis;
+
+ begin
+ Full_Analysis := False;
+ Expander_Mode_Save_And_Set (False);
+
+ Analyze (R_Copy);
+
+ if Nkind (R_Copy) in N_Subexpr
+ and then Is_Overloaded (R_Copy)
+ then
+ -- Apply preference rules for range of predefined integer types, or
+ -- diagnose true ambiguity.
+
+ declare
+ I : Interp_Index;
+ It : Interp;
+ Found : Entity_Id := Empty;
+
+ begin
+ Get_First_Interp (R_Copy, I, It);
+ while Present (It.Typ) loop
+ if Is_Discrete_Type (It.Typ) then
+ if No (Found) then
+ Found := It.Typ;
+ else
+ if Scope (Found) = Standard_Standard then
+ null;
+
+ elsif Scope (It.Typ) = Standard_Standard then
+ Found := It.Typ;
+
+ else
+ -- Both of them are user-defined
+
+ Error_Msg_N
+ ("ambiguous bounds in range of iteration", R_Copy);
+ Error_Msg_N ("\possible interpretations:", R_Copy);
+ Error_Msg_NE ("\\} ", R_Copy, Found);
+ Error_Msg_NE ("\\} ", R_Copy, It.Typ);
+ exit;
+ end if;
+ end if;
+ end if;
+
+ Get_Next_Interp (I, It);
+ end loop;
+ end;
+ end if;
+
+ -- Subtype mark in iteration scheme
+
+ if Is_Entity_Name (R_Copy)
+ and then Is_Type (Entity (R_Copy))
+ then
+ null;
+
+ -- Expression in range, or Ada 2012 iterator
+
+ elsif Nkind (R_Copy) in N_Subexpr then
+ Resolve (R_Copy);
+ end if;
+
+ Expander_Mode_Restore;
+ Full_Analysis := Save_Analysis;
+ end Pre_Analyze_Range;
+
end Sem_Ch5;
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index a9f84d34faa..780a916bc2d 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -268,14 +268,19 @@ package body Sem_Ch6 is
procedure Analyze_Expression_Function (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N);
LocX : constant Source_Ptr := Sloc (Expression (N));
- Def_Id : constant Entity_Id := Defining_Entity (Specification (N));
Expr : constant Node_Id := Expression (N);
- New_Body : Node_Id;
- New_Decl : Node_Id;
+ Spec : constant Node_Id := Specification (N);
- Prev : constant Entity_Id := Current_Entity_In_Scope (Def_Id);
+ Def_Id : Entity_Id;
+ pragma Unreferenced (Def_Id);
+
+ Prev : Entity_Id;
-- If the expression is a completion, Prev is the entity whose
- -- declaration is completed.
+ -- declaration is completed. Def_Id is needed to analyze the spec.
+
+ New_Body : Node_Id;
+ New_Decl : Node_Id;
+ New_Spec : Node_Id;
begin
-- This is one of the occasions on which we transform the tree during
@@ -286,10 +291,20 @@ package body Sem_Ch6 is
-- determine whether this is possible.
Inline_Processing_Required := True;
+ New_Spec := Copy_Separate_Tree (Spec);
+ Prev := Current_Entity_In_Scope (Defining_Entity (Spec));
+
+ -- If there are previous overloadable entities with the same name,
+ -- check whether any of them is completed by the expression function.
+
+ if Present (Prev) and then Is_Overloadable (Prev) then
+ Def_Id := Analyze_Subprogram_Specification (Spec);
+ Prev := Find_Corresponding_Spec (N);
+ end if;
New_Body :=
Make_Subprogram_Body (Loc,
- Specification => Copy_Separate_Tree (Specification (N)),
+ Specification => New_Spec,
Declarations => Empty_List,
Handled_Statement_Sequence =>
Make_Handled_Sequence_Of_Statements (LocX,
@@ -307,6 +322,7 @@ package body Sem_Ch6 is
Insert_After (N, New_Body);
Rewrite (N, Make_Null_Statement (Loc));
+ Set_Has_Completion (Prev, False);
Analyze (N);
Analyze (New_Body);
Set_Is_Inlined (Prev);
@@ -314,6 +330,7 @@ package body Sem_Ch6 is
elsif Present (Prev)
and then Comes_From_Source (Prev)
then
+ Set_Has_Completion (Prev, False);
Rewrite (N, New_Body);
Analyze (N);
@@ -333,8 +350,7 @@ package body Sem_Ch6 is
else
New_Decl :=
- Make_Subprogram_Declaration (Loc,
- Specification => Specification (N));
+ Make_Subprogram_Declaration (Loc, Specification => Spec);
Rewrite (N, New_Decl);
Analyze (N);
@@ -1469,9 +1485,19 @@ package body Sem_Ch6 is
-- extended_return_statement.
if Returns_Object then
- Error_Msg_N
- ("extended_return_statement cannot return value; " &
- "use `""RETURN;""`", N);
+ if Nkind (N) = N_Extended_Return_Statement then
+ Error_Msg_N
+ ("extended return statements cannot be nested; use `RETURN;`",
+ N);
+
+ -- Case of a simple return statement with a value inside extended
+ -- return statement.
+
+ else
+ Error_Msg_N
+ ("return nested in extended return statement cannot return " &
+ "value; use `RETURN;`", N);
+ end if;
end if;
else
@@ -8536,19 +8562,19 @@ package body Sem_Ch6 is
and then In_Private_Part (Current_Scope)
then
Priv_Decls :=
- Private_Declarations (
- Specification (Unit_Declaration_Node (Current_Scope)));
+ Private_Declarations
+ (Specification (Unit_Declaration_Node (Current_Scope)));
return In_Package_Body (Current_Scope)
or else
(Is_List_Member (Decl)
- and then List_Containing (Decl) = Priv_Decls)
+ and then List_Containing (Decl) = Priv_Decls)
or else (Nkind (Parent (Decl)) = N_Package_Specification
- and then not
- Is_Compilation_Unit
- (Defining_Entity (Parent (Decl)))
- and then List_Containing (Parent (Parent (Decl)))
- = Priv_Decls);
+ and then not
+ Is_Compilation_Unit
+ (Defining_Entity (Parent (Decl)))
+ and then List_Containing (Parent (Parent (Decl))) =
+ Priv_Decls);
else
return False;
end if;
@@ -9562,6 +9588,15 @@ package body Sem_Ch6 is
-- or IN OUT parameters of the subprogram, or (for a function) if the
-- return value has an invariant.
+ function Is_Public_Subprogram_For (T : Entity_Id) return Boolean;
+ -- T is the entity for a private type for which invariants are defined.
+ -- This function returns True if the procedure corresponding to the
+ -- value of Designator is a public procedure from the point of view of
+ -- this type (i.e. its spec is in the visible part of the package that
+ -- contains the declaration of the private type). A True value means
+ -- that an invariant check is required (for an IN OUT parameter, or
+ -- the returned value of a function.
+
--------------
-- Grab_PPC --
--------------
@@ -9689,6 +9724,45 @@ package body Sem_Ch6 is
return False;
end Invariants_Or_Predicates_Present;
+ ------------------------------
+ -- Is_Public_Subprogram_For --
+ ------------------------------
+
+ -- The type T is a private type, its declaration is therefore in
+ -- the list of public declarations of some package. The test for a
+ -- public subprogram is that its declaration is in this same list
+ -- of declarations for the same package (note that all the public
+ -- declarations are in one list, and all the private declarations
+ -- in another, so this deals with the public/private distinction).
+
+ function Is_Public_Subprogram_For (T : Entity_Id) return Boolean is
+ DD : constant Node_Id := Unit_Declaration_Node (Designator);
+ -- The subprogram declaration for the subprogram in question
+
+ TL : constant List_Id :=
+ Visible_Declarations
+ (Specification (Unit_Declaration_Node (Scope (T))));
+ -- The list of declarations containing the private declaration of
+ -- the type. We know it is a private type, so we know its scope is
+ -- the package in question, and we know it must be in the visible
+ -- declarations of this package.
+
+ begin
+ -- If the subprogram declaration is not a list member, it must be
+ -- an Init_Proc, in which case we want to consider it to be a
+ -- public subprogram, since we do get initializations to deal with.
+
+ if not Is_List_Member (DD) then
+ return True;
+
+ -- Otherwise we test whether the subprogram is declared in the
+ -- visible declarations of the package containing the type.
+
+ else
+ return TL = List_Containing (DD);
+ end if;
+ end Is_Public_Subprogram_For;
+
-- Start of processing for Process_PPCs
begin
@@ -9985,10 +10059,13 @@ package body Sem_Ch6 is
Parameter_Type => New_Occurrence_Of (Ftyp, Loc),
Defining_Identifier => Rent));
- -- Add invariant call if returning type with invariants
+ -- Add invariant call if returning type with invariants and
+ -- this is a public function, i.e. a function declared in the
+ -- visible part of the package defining the private type.
if Has_Invariants (Etype (Rent))
and then Present (Invariant_Procedure (Etype (Rent)))
+ and then Is_Public_Subprogram_For (Etype (Rent))
then
Append_To (Plist,
Make_Invariant_Call (New_Occurrence_Of (Rent, Loc)));
@@ -10017,6 +10094,7 @@ package body Sem_Ch6 is
if Has_Invariants (Ftype)
and then Present (Invariant_Procedure (Ftype))
+ and then Is_Public_Subprogram_For (Ftype)
then
Append_To (Plist,
Make_Invariant_Call
diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb
index 17f802fc14e..98913dbccce 100644
--- a/gcc/ada/sem_ch8.adb
+++ b/gcc/ada/sem_ch8.adb
@@ -52,6 +52,7 @@ with Sem_Ch3; use Sem_Ch3;
with Sem_Ch4; use Sem_Ch4;
with Sem_Ch6; use Sem_Ch6;
with Sem_Ch12; use Sem_Ch12;
+with Sem_Ch13; use Sem_Ch13;
with Sem_Disp; use Sem_Disp;
with Sem_Dist; use Sem_Dist;
with Sem_Eval; use Sem_Eval;
@@ -2848,6 +2849,13 @@ package body Sem_Ch8 is
("?redundant renaming, entity is directly visible", Name (N));
end if;
+ -- Implementation-defined aspect specifications can appear in a renaming
+ -- declaration, but not language-defined ones.
+
+ if Has_Aspects (N) then
+ Analyze_Aspect_Specifications (N, New_S);
+ end if;
+
Ada_Version := Save_AV;
Ada_Version_Explicit := Save_AV_Exp;
end Analyze_Subprogram_Renaming;
diff --git a/gcc/ada/sem_ch9.adb b/gcc/ada/sem_ch9.adb
index 4b284cd9599..35c4eeebda0 100644
--- a/gcc/ada/sem_ch9.adb
+++ b/gcc/ada/sem_ch9.adb
@@ -905,6 +905,83 @@ package body Sem_Ch9 is
Bad_Predicated_Subtype_Use
("subtype& has predicate, not allowed in entry family",
D_Sdef, Etype (D_Sdef));
+
+ -- Check entry family static bounds outside allowed limits
+
+ -- Note: originally this check was not performed here, but in that
+ -- case the check happens deep in the expander, and the message is
+ -- posted at the wrong location, and omitted in -gnatc mode.
+ -- If the type of the entry index is a generic formal, no check
+ -- is possible. In an instance, the check is not static and a run-
+ -- time exception will be raised if the bounds are unreasonable.
+
+ declare
+ PEI : constant Entity_Id := RTE (RE_Protected_Entry_Index);
+ LB : constant Uint := Expr_Value (Type_Low_Bound (PEI));
+ UB : constant Uint := Expr_Value (Type_High_Bound (PEI));
+
+ LBR : Node_Id;
+ UBR : Node_Id;
+
+ begin
+
+ -- No bounds checking if the type is generic or if previous error.
+ -- In an instance the check is dynamic.
+
+ if Is_Generic_Type (Etype (D_Sdef))
+ or else In_Instance
+ or else Error_Posted (D_Sdef)
+ then
+ goto Skip_LB;
+
+ elsif Nkind (D_Sdef) = N_Range then
+ LBR := Low_Bound (D_Sdef);
+
+ elsif Is_Entity_Name (D_Sdef)
+ and then Is_Type (Entity (D_Sdef))
+ then
+ LBR := Type_Low_Bound (Entity (D_Sdef));
+
+ else
+ goto Skip_LB;
+ end if;
+
+ if Is_Static_Expression (LBR)
+ and then Expr_Value (LBR) < LB
+ then
+ Error_Msg_Uint_1 := LB;
+ Error_Msg_N ("entry family low bound must be '>'= ^!", D_Sdef);
+ end if;
+
+ <<Skip_LB>>
+ if Is_Generic_Type (Etype (D_Sdef))
+ or else In_Instance
+ or else Error_Posted (D_Sdef)
+ then
+ goto Skip_UB;
+
+ elsif Nkind (D_Sdef) = N_Range then
+ UBR := High_Bound (D_Sdef);
+
+ elsif Is_Entity_Name (D_Sdef)
+ and then Is_Type (Entity (D_Sdef))
+ then
+ UBR := Type_High_Bound (Entity (D_Sdef));
+
+ else
+ goto Skip_UB;
+ end if;
+
+ if Is_Static_Expression (UBR)
+ and then Expr_Value (UBR) > UB
+ then
+ Error_Msg_Uint_1 := UB;
+ Error_Msg_N ("entry family high bound must be '<'= ^!", D_Sdef);
+ end if;
+
+ <<Skip_UB>>
+ null;
+ end;
end if;
-- Decorate Def_Id
diff --git a/gcc/ada/sem_elab.adb b/gcc/ada/sem_elab.adb
index 5df43afc43e..ce4cff39d92 100644
--- a/gcc/ada/sem_elab.adb
+++ b/gcc/ada/sem_elab.adb
@@ -2130,7 +2130,32 @@ package body Sem_Elab is
end if;
-- Here is the case of calling a subprogram where the body has not yet
- -- been encountered, a warning message is needed.
+ -- been encountered. A warning message is needed, except if this is the
+ -- case of appearing within an aspect specification that results in
+ -- a check call, we do not really have such a situation, so no warning
+ -- is needed (e.g. the case of a precondition, where the call appears
+ -- textually before the body, but in actual fact is moved to the
+ -- appropriate subprogram body and so does not need a check).
+
+ declare
+ P : Node_Id;
+ begin
+ P := Parent (N);
+ loop
+ if Nkind (P) in N_Subexpr then
+ P := Parent (P);
+ elsif Nkind (P) = N_If_Statement
+ and then Nkind (Original_Node (P)) = N_Pragma
+ and then Present (Corresponding_Aspect (Original_Node (P)))
+ then
+ return;
+ else
+ exit;
+ end if;
+ end loop;
+ end;
+
+ -- Not that special case, warning and dynamic check is required
-- If we have nothing in the call stack, then this is at the outer
-- level, and the ABE is bound to occur.
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index 397c73380a2..a21358bd791 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -3524,19 +3524,39 @@ package body Sem_Prag is
("second argument of pragma% must be a subprogram", Arg2);
end if;
- -- For Stdcall, a subprogram, variable or subprogram type is required
+ -- Stdcall case
- if C = Convention_Stdcall
- and then not Is_Subprogram (E)
- and then not Is_Generic_Subprogram (E)
- and then Ekind (E) /= E_Variable
- and then not
- (Is_Access_Type (E)
- and then Ekind (Designated_Type (E)) = E_Subprogram_Type)
- then
- Error_Pragma_Arg
- ("second argument of pragma% must be subprogram (type)",
- Arg2);
+ if C = Convention_Stdcall then
+
+ -- A dispatching call is not allowed. A dispatching subprogram
+ -- cannot be used to interface to the Win32 API, so in fact this
+ -- check does not impose any effective restriction.
+
+ if Is_Dispatching_Operation (E) then
+
+ Error_Pragma
+ ("dispatching subprograms cannot use Stdcall convention");
+
+ -- Subprogram is allowed, but not a generic subprogram, and not a
+ -- dispatching operation.
+
+ elsif not Is_Subprogram (E)
+ and then not Is_Generic_Subprogram (E)
+
+ -- A variable is OK
+
+ and then Ekind (E) /= E_Variable
+
+ -- An access to subprogram is also allowed
+
+ and then not
+ (Is_Access_Type (E)
+ and then Ekind (Designated_Type (E)) = E_Subprogram_Type)
+ then
+ Error_Pragma_Arg
+ ("second argument of pragma% must be subprogram (type)",
+ Arg2);
+ end if;
end if;
if not Is_Subprogram (E)
@@ -5337,6 +5357,46 @@ package body Sem_Prag is
Check_Restriction (No_Implementation_Restrictions, Arg);
end if;
+ -- Special processing for No_Elaboration_Code restriction
+
+ if R_Id = No_Elaboration_Code then
+
+ -- Restriction is only recognized within a configuration
+ -- pragma file, or within a unit of the main extended
+ -- program. Note: the test for Main_Unit is needed to
+ -- properly include the case of configuration pragma files.
+
+ if not (Current_Sem_Unit = Main_Unit
+ or else In_Extended_Main_Source_Unit (N))
+ then
+ return;
+
+ -- Don't allow in a subunit unless already specified in
+ -- body or spec.
+
+ elsif Nkind (Parent (N)) = N_Compilation_Unit
+ and then Nkind (Unit (Parent (N))) = N_Subunit
+ and then not Restriction_Active (No_Elaboration_Code)
+ then
+ Error_Msg_N
+ ("invalid specification of ""No_Elaboration_Code""",
+ N);
+ Error_Msg_N
+ ("\restriction cannot be specified in a subunit", N);
+ Error_Msg_N
+ ("\unless also specified in body or spec", N);
+ return;
+
+ -- If we have a No_Elaboration_Code pragma that we
+ -- accept, then it needs to be added to the configuration
+ -- restrcition set so that we get proper application to
+ -- other units in the main extended source as required.
+
+ else
+ Add_To_Config_Boolean_Restrictions (No_Elaboration_Code);
+ end if;
+ end if;
+
-- If this is a warning, then set the warning unless we already
-- have a real restriction active (we never want a warning to
-- override a real restriction).
@@ -12647,6 +12707,47 @@ package body Sem_Prag is
end if;
end Pure_05;
+ -------------
+ -- Pure_12 --
+ -------------
+
+ -- pragma Pure_12 [(library_unit_NAME)];
+
+ -- This pragma is useable only in GNAT_Mode, where it is used like
+ -- pragma Pure but it is only effective in Ada 2012 mode (otherwise
+ -- it is ignored). It may be used after a pragma Preelaborate, in
+ -- which case it overrides the effect of the pragma Preelaborate.
+ -- This is used to implement AI05-0212 which recategorizes some
+ -- run-time packages in Ada 2012 mode.
+
+ when Pragma_Pure_12 => Pure_12 : declare
+ Ent : Entity_Id;
+
+ begin
+ GNAT_Pragma;
+ Check_Valid_Library_Unit_Pragma;
+
+ if not GNAT_Mode then
+ Error_Pragma ("pragma% only available in GNAT mode");
+ end if;
+
+ if Nkind (N) = N_Null_Statement then
+ return;
+ end if;
+
+ -- This is one of the few cases where we need to test the value of
+ -- Ada_Version_Explicit rather than Ada_Version (which is always
+ -- set to Ada_2012 in a predefined unit), we need to know the
+ -- explicit version set to know if this pragma is active.
+
+ if Ada_Version_Explicit >= Ada_2012 then
+ Ent := Find_Lib_Unit_Name;
+ Set_Is_Preelaborated (Ent, False);
+ Set_Is_Pure (Ent);
+ Set_Suppress_Elaboration_Warnings (Ent);
+ end if;
+ end Pure_12;
+
-------------------
-- Pure_Function --
-------------------
@@ -14427,7 +14528,7 @@ package body Sem_Prag is
end;
end if;
- -- Two or more arguments (must be two)
+ -- Two or more arguments (must be two)
else
Check_Arg_Is_One_Of (Arg1, Name_On, Name_Off);
@@ -14446,8 +14547,7 @@ package body Sem_Prag is
-- the formal may be wrapped in a conversion if the
-- actual is a conversion. Retrieve the real entity name.
- if (In_Instance_Body
- or else In_Inlined_Body)
+ if (In_Instance_Body or else In_Inlined_Body)
and then Nkind (E_Id) = N_Unchecked_Type_Conversion
then
E_Id := Expression (E_Id);
@@ -14511,10 +14611,21 @@ package body Sem_Prag is
-- In any other case, an error will be signalled (ON
-- with no matching OFF).
+ -- Note: We set Used if we are inside a generic to
+ -- disable the test that the non-config case actually
+ -- cancels a warning. That's because we can't be sure
+ -- there isn't an instantiation in some other unit
+ -- where a warning is suppressed.
+
+ -- We could do a little better here by checking if the
+ -- generic unit we are inside is public, but for now
+ -- we don't bother with that refinement.
+
if Chars (Argx) = Name_Off then
Set_Specific_Warning_Off
(Loc, Name_Buffer (1 .. Name_Len),
- Config => Is_Configuration_Pragma);
+ Config => Is_Configuration_Pragma,
+ Used => Inside_A_Generic or else In_Instance);
elsif Chars (Argx) = Name_On then
Set_Specific_Warning_On
@@ -14959,6 +15070,7 @@ package body Sem_Prag is
Pragma_Psect_Object => -1,
Pragma_Pure => -1,
Pragma_Pure_05 => -1,
+ Pragma_Pure_12 => -1,
Pragma_Pure_Function => -1,
Pragma_Queuing_Policy => -1,
Pragma_Ravenscar => -1,
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index ad59f952252..a240781dc8a 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -2811,7 +2811,7 @@ package body Sem_Res is
-- default expression mode (the Freeze_Expression routine tests this
-- flag and only freezes static types if it is set).
- -- AI05-177 (Ada2012): Expression functions do not freeze. Only
+ -- Ada 2012 (AI05-177): Expression functions do not freeze. Only
-- their use (in an expanded call) freezes.
if Ekind (Current_Scope) /= E_Function
@@ -4086,7 +4086,7 @@ package body Sem_Res is
is
begin
if Type_Access_Level (Etype (Disc_Exp)) >
- Type_Access_Level (Alloc_Typ)
+ Deepest_Type_Access_Level (Alloc_Typ)
then
Error_Msg_N
("operand type has deeper level than allocator type", Disc_Exp);
@@ -4095,10 +4095,10 @@ package body Sem_Res is
-- object must not be deeper than that of the allocator's type.
elsif Nkind (Disc_Exp) = N_Attribute_Reference
- and then Get_Attribute_Id (Attribute_Name (Disc_Exp))
- = Attribute_Access
- and then Object_Access_Level (Prefix (Disc_Exp))
- > Type_Access_Level (Alloc_Typ)
+ and then Get_Attribute_Id (Attribute_Name (Disc_Exp)) =
+ Attribute_Access
+ and then Object_Access_Level (Prefix (Disc_Exp)) >
+ Deepest_Type_Access_Level (Alloc_Typ)
then
Error_Msg_N
("prefix of attribute has deeper level than allocator type",
@@ -4109,8 +4109,8 @@ package body Sem_Res is
elsif Ekind (Etype (Disc_Exp)) = E_Anonymous_Access_Type
and then Nkind (Disc_Exp) = N_Selected_Component
- and then Object_Access_Level (Prefix (Disc_Exp))
- > Type_Access_Level (Alloc_Typ)
+ and then Object_Access_Level (Prefix (Disc_Exp)) >
+ Deepest_Type_Access_Level (Alloc_Typ)
then
Error_Msg_N
("access discriminant has deeper level than allocator type",
@@ -4314,7 +4314,9 @@ package body Sem_Res is
Exp_Typ := Entity (E);
end if;
- if Type_Access_Level (Exp_Typ) > Type_Access_Level (Typ) then
+ if Type_Access_Level (Exp_Typ) >
+ Deepest_Type_Access_Level (Typ)
+ then
if In_Instance_Body then
Error_Msg_N ("?type in allocator has deeper level than" &
" designated class-wide type", E);
@@ -8666,7 +8668,15 @@ package body Sem_Res is
-- this by making sure that the expanded code points to
-- the Sloc of the expression, not the original pragma.
- Error_Msg_N
+ -- Note: Use Error_Msg_F here rather than Error_Msg_N.
+ -- The source location of the expression is not usually
+ -- the best choice here. For example, it gets located on
+ -- the last AND keyword in a chain of boolean expressiond
+ -- AND'ed together. It is best to put the message on the
+ -- first character of the assertion, which is the effect
+ -- of the First_Node call here.
+
+ Error_Msg_F
("?assertion would fail at run time!",
Expression
(First (Pragma_Argument_Associations (Orig))));
@@ -8691,8 +8701,14 @@ package body Sem_Res is
and then Entity (Expr) = Standard_False
then
null;
+
+ -- Post warning
+
else
- Error_Msg_N
+ -- Again use Error_Msg_F rather than Error_Msg_N, see
+ -- comment above for an explanation of why we do this.
+
+ Error_Msg_F
("?check would fail at run time!",
Expression
(Last (Pragma_Argument_Associations (Orig))));
@@ -10358,13 +10374,15 @@ package body Sem_Res is
Subtypes_Statically_Match (Target_Comp_Type, Opnd_Comp_Type)
then
if Type_Access_Level (Target_Type) <
- Type_Access_Level (Opnd_Type)
+ Deepest_Type_Access_Level (Opnd_Type)
then
if In_Instance_Body then
- Error_Msg_N ("?source array type " &
- "has deeper accessibility level than target", Operand);
- Error_Msg_N ("\?Program_Error will be raised at run time",
- Operand);
+ Error_Msg_N
+ ("?source array type has " &
+ "deeper accessibility level than target", Operand);
+ Error_Msg_N
+ ("\?Program_Error will be raised at run time",
+ Operand);
Rewrite (N,
Make_Raise_Program_Error (Sloc (N),
Reason => PE_Accessibility_Check_Failed));
@@ -10374,8 +10392,9 @@ package body Sem_Res is
-- Conversion not allowed because of accessibility levels
else
- Error_Msg_N ("source array type " &
- "has deeper accessibility level than target", Operand);
+ Error_Msg_N
+ ("source array type has " &
+ "deeper accessibility level than target", Operand);
return False;
end if;
@@ -10398,7 +10417,7 @@ package body Sem_Res is
-- All of this is checked in Subtypes_Statically_Match.
if not Subtypes_Statically_Match
- (Target_Comp_Type, Opnd_Comp_Type)
+ (Target_Comp_Type, Opnd_Comp_Type)
then
Error_Msg_N
("component subtypes must statically match", Operand);
@@ -11069,6 +11088,11 @@ package body Sem_Res is
N);
return True;
+ -- If it was legal in the generic, it's legal in the instance
+
+ elsif In_Instance_Body then
+ return True;
+
-- If both are tagged types, check legality of view conversions
elsif Is_Tagged_Type (Target_Type)
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 1764da9db02..edf1fecbfe6 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -2437,6 +2437,12 @@ package body Sem_Util is
(Defining_Identifier
(Associated_Node_For_Itype (Typ))));
+ -- For generic formal type, return Int'Last (infinite).
+ -- See comment preceding Is_Generic_Type call in Type_Access_Level.
+
+ elsif Is_Generic_Type (Root_Type (Typ)) then
+ return UI_From_Int (Int'Last);
+
else
return Type_Access_Level (Typ);
end if;
@@ -6583,10 +6589,6 @@ package body Sem_Util is
if Is_Entity_Name (Obj) then
E := Entity (Obj);
- if Is_Object (E) and then not Is_Aliased (E) then
- Check_Restriction (No_Implicit_Aliasing, Obj);
- end if;
-
return
(Is_Object (E)
and then
@@ -8731,10 +8733,15 @@ package body Sem_Util is
then
return True;
- elsif Nkind (N) = N_Indexed_Component
- or else Nkind (N) = N_Selected_Component
+ elsif Nkind_In (N, N_Indexed_Component, N_Selected_Component)
+ and then Is_Volatile_Prefix (Prefix (N))
then
- return Is_Volatile_Prefix (Prefix (N));
+ return True;
+
+ elsif Nkind (N) = N_Selected_Component
+ and then Is_Volatile (Entity (Selector_Name (N)))
+ then
+ return True;
else
return False;
@@ -10837,9 +10844,7 @@ package body Sem_Util is
-- source. This excludes, for example, calls to a dispatching
-- assignment operation when the left-hand side is tagged.
- if Modification_Comes_From_Source
- or else Alfa_Mode
- then
+ if Modification_Comes_From_Source or else Alfa_Mode then
Generate_Reference (Ent, Exp, 'm');
-- If the target of the assignment is the bound variable
@@ -12715,6 +12720,25 @@ package body Sem_Util is
end if;
end if;
+ -- Return library level for a generic formal type. This is done because
+ -- RM(10.3.2) says that "The statically deeper relationship does not
+ -- apply to ... a descendant of a generic formal type". Rather than
+ -- checking at each point where a static accessibility check is
+ -- performed to see if we are dealing with a formal type, this rule is
+ -- implemented by having Type_Access_Level and Deepest_Type_Access_Level
+ -- return extreme values for a formal type; Deepest_Type_Access_Level
+ -- returns Int'Last. By calling the appropriate function from among the
+ -- two, we ensure that the static accessibility check will pass if we
+ -- happen to run into a formal type. More specifically, we should call
+ -- Deepest_Type_Access_Level instead of Type_Access_Level whenever the
+ -- call occurs as part of a static accessibility check and the error
+ -- case is the case where the type's level is too shallow (as opposed
+ -- to too deep).
+
+ if Is_Generic_Type (Root_Type (Btyp)) then
+ return Scope_Depth (Standard_Standard);
+ end if;
+
return Scope_Depth (Enclosing_Dynamic_Scope (Btyp));
end Type_Access_Level;
diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads
index c7f610d52f0..693ddf2def9 100644
--- a/gcc/ada/sem_util.ads
+++ b/gcc/ada/sem_util.ads
@@ -314,7 +314,9 @@ package Sem_Util is
-- static accesssibility level of the object. In that case, the dynamic
-- accessibility level of the object may take on values in a range. The low
-- bound of of that range is returned by Type_Access_Level; this function
- -- yields the high bound of that range.
+ -- yields the high bound of that range. Also differs from Type_Access_Level
+ -- in the case of a descendant of a generic formal type (returns Int'Last
+ -- instead of 0).
function Defining_Entity (N : Node_Id) return Entity_Id;
-- Given a declaration N, returns the associated defining entity. If the
@@ -775,8 +777,12 @@ package Sem_Util is
function Is_Aliased_View (Obj : Node_Id) return Boolean;
-- Determine if Obj is an aliased view, i.e. the name of an object to which
- -- 'Access or 'Unchecked_Access can apply. Note that the implementation
- -- takes the No_Implicit_Aiasing restriction into account.
+ -- 'Access or 'Unchecked_Access can apply. Note that this routine uses the
+ -- rules of the language, it does not take into account the restriction
+ -- No_Implicit_Aliasing, so it can return True if the restriction is active
+ -- and Obj violates the restriction. The caller is responsible for calling
+ -- Restrict.Check_No_Implicit_Aliasing if True is returned, but there is a
+ -- requirement for obeying the restriction in the call context.
function Is_Ancestor_Package
(E1 : Entity_Id;
diff --git a/gcc/ada/sinfo.adb b/gcc/ada/sinfo.adb
index b36b930b8c4..440cf02a2e7 100644
--- a/gcc/ada/sinfo.adb
+++ b/gcc/ada/sinfo.adb
@@ -657,6 +657,7 @@ package body Sinfo is
(N : Node_Id) return Node_Id is
begin
pragma Assert (False
+ or else NT (N).Nkind = N_Expression_Function
or else NT (N).Nkind = N_Package_Body
or else NT (N).Nkind = N_Protected_Body
or else NT (N).Nkind = N_Subprogram_Body
@@ -1572,6 +1573,14 @@ package body Sinfo is
return Flag13 (N);
end Has_Wide_Wide_Character;
+ function Header_Size_Added
+ (N : Node_Id) return Boolean is
+ begin
+ pragma Assert (False
+ or else NT (N).Nkind = N_Attribute_Reference);
+ return Flag11 (N);
+ end Header_Size_Added;
+
function Hidden_By_Use_Clause
(N : Node_Id) return Elist_Id is
begin
@@ -3729,6 +3738,7 @@ package body Sinfo is
(N : Node_Id; Val : Node_Id) is
begin
pragma Assert (False
+ or else NT (N).Nkind = N_Expression_Function
or else NT (N).Nkind = N_Package_Body
or else NT (N).Nkind = N_Protected_Body
or else NT (N).Nkind = N_Subprogram_Body
@@ -4635,6 +4645,14 @@ package body Sinfo is
Set_Flag13 (N, Val);
end Set_Has_Wide_Wide_Character;
+ procedure Set_Header_Size_Added
+ (N : Node_Id; Val : Boolean := True) is
+ begin
+ pragma Assert (False
+ or else NT (N).Nkind = N_Attribute_Reference);
+ Set_Flag11 (N, Val);
+ end Set_Header_Size_Added;
+
procedure Set_Hidden_By_Use_Clause
(N : Node_Id; Val : Elist_Id) is
begin
diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads
index 35a73f9ad94..7e308ec328e 100644
--- a/gcc/ada/sinfo.ads
+++ b/gcc/ada/sinfo.ads
@@ -760,6 +760,9 @@ package Sinfo is
-- renaming declaration when it is a Renaming_As_Body. The field is Empty
-- if there is no corresponding spec, as in the case of a subprogram body
-- that serves as its own spec.
+ --
+ -- In Ada 2012, Corresponding_Spec is set on expression functions that
+ -- complete a subprogram declaration.
-- Corresponding_Stub (Node3-Sem)
-- This field is present in an N_Subunit node. It holds the node in
@@ -1203,6 +1206,13 @@ package Sinfo is
-- code outside the Wide_Character range) appears in the string. Used to
-- implement pragma preference rules.
+ -- Header_Size_Added (Flag11-Sem)
+ -- Present in N_Attribute_Reference nodes, set only for attribute
+ -- Max_Size_In_Storage_Elements. The flag indicates that the size of the
+ -- hidden list header used by the runtime finalization support has been
+ -- added to the size of the prefix. The flag also prevents the infinite
+ -- expansion of the same attribute in the said context.
+
-- Hidden_By_Use_Clause (Elist4-Sem)
-- An entity list present in use clauses that appear within
-- instantiations. For the resolution of local entities, entities
@@ -3324,6 +3334,7 @@ package Sinfo is
-- Entity (Node4-Sem) used if the attribute yields a type
-- Associated_Node (Node4-Sem)
-- Do_Overflow_Check (Flag17-Sem)
+ -- Header_Size_Added (Flag11-Sem)
-- Redundant_Use (Flag13-Sem)
-- Must_Be_Byte_Aligned (Flag14)
-- plus fields for expression
@@ -4607,6 +4618,7 @@ package Sinfo is
-- Sloc points to FUNCTION
-- Specification (Node1)
-- Expression (Node3)
+ -- Corresponding_Spec (Node5-Sem)
-----------------------------------
-- 6.4 Procedure Call Statement --
@@ -7310,6 +7322,11 @@ package Sinfo is
-- more sense to call it an Expression field, but then we would have to
-- special case the treatment of the N_Reference node.
+ -- Note: evaluating a N_Reference node is guaranteed to yield a non-null
+ -- value at run time. Therefore, it is valid to set Is_Known_Non_Null on
+ -- a temporary initialized to a N_Reference node in order to eliminate
+ -- superfluous access checks.
+
-- Sprint syntax: prefix'reference
-- N_Reference
@@ -8547,6 +8564,9 @@ package Sinfo is
function Has_Wide_Wide_Character
(N : Node_Id) return Boolean; -- Flag13
+ function Header_Size_Added
+ (N : Node_Id) return Boolean; -- Flag11
+
function Hidden_By_Use_Clause
(N : Node_Id) return Elist_Id; -- Elist4
@@ -9522,6 +9542,9 @@ package Sinfo is
procedure Set_Has_Wide_Wide_Character
(N : Node_Id; Val : Boolean := True); -- Flag13
+ procedure Set_Header_Size_Added
+ (N : Node_Id; Val : Boolean := True); -- Flag11
+
procedure Set_Hidden_By_Use_Clause
(N : Node_Id; Val : Elist_Id); -- Elist4
@@ -11918,6 +11941,7 @@ package Sinfo is
pragma Inline (Has_Task_Name_Pragma);
pragma Inline (Has_Wide_Character);
pragma Inline (Has_Wide_Wide_Character);
+ pragma Inline (Header_Size_Added);
pragma Inline (Hidden_By_Use_Clause);
pragma Inline (High_Bound);
pragma Inline (Identifier);
@@ -12239,6 +12263,7 @@ package Sinfo is
pragma Inline (Set_Has_Task_Name_Pragma);
pragma Inline (Set_Has_Wide_Character);
pragma Inline (Set_Has_Wide_Wide_Character);
+ pragma Inline (Set_Header_Size_Added);
pragma Inline (Set_Hidden_By_Use_Clause);
pragma Inline (Set_High_Bound);
pragma Inline (Set_Identifier);
diff --git a/gcc/ada/sinput.ads b/gcc/ada/sinput.ads
index bdc268eaf0f..1d13f6e60be 100644
--- a/gcc/ada/sinput.ads
+++ b/gcc/ada/sinput.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- --
@@ -43,7 +43,7 @@
-- described in RM 2.2 (13). Any of the characters FF, LF, CR or VT or any
-- wide character that is a Line or Paragraph Separator acts as an end of
-- logical line in this sense, and it is essentially irrelevant whether one
--- or more appears in sequence (since if sequence of such characters is
+-- or more appears in sequence (since if a sequence of such characters is
-- regarded as separate ends of line, then the intervening logical lines
-- are null in any case).
@@ -451,6 +451,75 @@ package Sinput is
Internal_Source'Unrestricted_Access;
-- Pointer to internal source buffer
+ -----------------------------------------
+ -- Handling of Source Line Terminators --
+ -----------------------------------------
+
+ -- In this section we discuss in detail the issue of terminators used to
+ -- terminate source lines. The RM says that one or more format effectors
+ -- (other than horizontal tab) end a source line, and defines the set of
+ -- such format effectors, but does not talk about exactly how they are
+ -- represented in the source program (since in general the RM is not in
+ -- the business of specifying source program formats).
+
+ -- The type Types.Line_Terminator is defined as a subtype of Character
+ -- that includes CR/LF/VT/FF. The most common line enders in practice
+ -- are CR (some MAC systems), LF (Unix systems), and CR/LF (DOS/Windows
+ -- systems). Any of these sequences is recognized as ending a physical
+ -- source line, and if multiple such terminators appear (e.g. LF/LF),
+ -- then we consider we have an extra blank line.
+
+ -- VT and FF are recognized as terminating source lines, but they are
+ -- considered to end a logical line instead of a physical line, so that
+ -- the line numbering ignores such terminators. The use of VT and FF is
+ -- mandated by the standard, and correctly handled in a conforming manner
+ -- by GNAT, but their use is not recommended.
+
+ -- In addition to the set of characters defined by the type in Types, in
+ -- wide character encoding, then the codes returning True for a call to
+ -- System.UTF_32.Is_UTF_32_Line_Terminator are also recognized as ending a
+ -- source line. This includes the standard codes defined above in addition
+ -- to NEL (NEXT LINE), LINE SEPARATOR and PARAGRAPH SEPARATOR. Again, as in
+ -- the case of VT and FF, the standard requires we recognize these as line
+ -- terminators, but we consider them to be logical line terminators. The
+ -- only physical line terminators recognized are the standard ones (CR,
+ -- LF, or CR/LF).
+
+ -- However, we do not recognize the NEL (16#85#) character as having the
+ -- significance of an end of line character when operating in normal 8-bit
+ -- Latin-n input mode for the compiler. Instead the rule in this mode is
+ -- that all upper half control codes (16#80# .. 16#9F#) are illegal if they
+ -- occur in program text, and are ignored if they appear in comments.
+
+ -- First, note that this behavior is fully conforming with the standard.
+ -- The standard has nothing whatever to say about source representation
+ -- and implementations are completely free to make there own rules. In
+ -- this case, in 8-bit mode, GNAT decides that the 16#0085# character is
+ -- not a representation of the NEL character, even though it looks like it.
+ -- If you have NEL's in your program, which you expect to be treated as
+ -- end of line characters, you must use a wide character encoding such as
+ -- UTF-8 for this code to be recognized.
+
+ -- Second, an explanation of why we take this slightly surprising choice.
+ -- We have never encountered anyone actually using the NEL character to
+ -- end lines. One user raised the issue as a result of some experiments,
+ -- but no one has ever submitted a program encoded this way, in any of
+ -- the possible encodings. It seems that even when using wide character
+ -- codes extensively, the normal approach is to use standard line enders
+ -- (LF or CR/LF). So the failure to recognize NEL in this mode seems to
+ -- have no practical downside.
+
+ -- Moreover, what we have seen in a significant number of programs from
+ -- multiple sources is the practice of writing all program text in lower
+ -- half (ASCII) form, but using UTF-8 encoded wide characters freely in
+ -- comments, where the comments are terminated by normal line endings
+ -- (LF or CR/LF). The comments do not contain NEL codes, but they can and
+ -- do contain other UTF-8 encoding sequences where one of the bytes is the
+ -- NEL code. Now such programs can of course be compiled in UTF-8 mode,
+ -- but in practice they also compile fine in standard 8-bit mode without
+ -- specifying a character encoding. Since this is common practice, it would
+ -- be a signficant upwards incompatibility to recognize NEL in 8-bit mode.
+
-----------------
-- Subprograms --
-----------------
diff --git a/gcc/ada/snames.ads-tmpl b/gcc/ada/snames.ads-tmpl
index 3ed2a668e00..d15892a5f02 100644
--- a/gcc/ada/snames.ads-tmpl
+++ b/gcc/ada/snames.ads-tmpl
@@ -524,6 +524,7 @@ package Snames is
Name_Psect_Object : constant Name_Id := N + $; -- VMS
Name_Pure : constant Name_Id := N + $;
Name_Pure_05 : constant Name_Id := N + $; -- GNAT
+ Name_Pure_12 : constant Name_Id := N + $; -- GNAT
Name_Pure_Function : constant Name_Id := N + $; -- GNAT
Name_Relative_Deadline : constant Name_Id := N + $; -- Ada 05
Name_Remote_Call_Interface : constant Name_Id := N + $;
@@ -1672,6 +1673,7 @@ package Snames is
Pragma_Psect_Object,
Pragma_Pure,
Pragma_Pure_05,
+ Pragma_Pure_12,
Pragma_Pure_Function,
Pragma_Relative_Deadline,
Pragma_Remote_Call_Interface,
diff --git a/gcc/ada/sysdep.c b/gcc/ada/sysdep.c
index 4d383fd0608..a4456f56a24 100644
--- a/gcc/ada/sysdep.c
+++ b/gcc/ada/sysdep.c
@@ -80,54 +80,6 @@ extern struct tm *localtime_r(const time_t *, struct tm *);
#endif
/*
- mode_read_text
- open text file for reading
- rt for DOS and Windows NT, r for Unix
-
- mode_write_text
- truncate to zero length or create text file for writing
- wt for DOS and Windows NT, w for Unix
-
- mode_append_text
- append; open or create text file for writing at end-of-file
- at for DOS and Windows NT, a for Unix
-
- mode_read_binary
- open binary file for reading
- rb for DOS and Windows NT, r for Unix
-
- mode_write_binary
- truncate to zero length or create binary file for writing
- wb for DOS and Windows NT, w for Unix
-
- mode_append_binary
- append; open or create binary file for writing at end-of-file
- ab for DOS and Windows NT, a for Unix
-
- mode_read_text_plus
- open text file for update (reading and writing)
- r+t for DOS and Windows NT, r+ for Unix
-
- mode_write_text_plus
- truncate to zero length or create text file for update
- w+t for DOS and Windows NT, w+ for Unix
-
- mode_append_text_plus
- append; open or create text file for update, writing at end-of-file
- a+t for DOS and Windows NT, a+ for Unix
-
- mode_read_binary_plus
- open binary file for update (reading and writing)
- r+b for DOS and Windows NT, r+ for Unix
-
- mode_write_binary_plus
- truncate to zero length or create binary file for update
- w+b for DOS and Windows NT, w+ for Unix
-
- mode_append_binary_plus
- append; open or create binary file for update, writing at end-of-file
- a+b for DOS and Windows NT, a+ for Unix
-
Notes:
(1) Opening a file with read mode fails if the file does not exist or
@@ -169,18 +121,7 @@ extern struct tm *localtime_r(const time_t *, struct tm *);
*/
#if defined(WINNT)
-static const char *mode_read_text = "rt";
-static const char *mode_write_text = "wt";
-static const char *mode_append_text = "at";
-static const char *mode_read_binary = "rb";
-static const char *mode_write_binary = "wb";
-static const char *mode_append_binary = "ab";
-static const char *mode_read_text_plus = "r+t";
-static const char *mode_write_text_plus = "w+t";
-static const char *mode_append_text_plus = "a+t";
-static const char *mode_read_binary_plus = "r+b";
-static const char *mode_write_binary_plus = "w+b";
-static const char *mode_append_binary_plus = "a+b";
+
const char __gnat_text_translation_required = 1;
void
@@ -261,18 +202,6 @@ __gnat_get_stack_bounds (void **base, void **limit)
#else
-static const char *mode_read_text = "r";
-static const char *mode_write_text = "w";
-static const char *mode_append_text = "a";
-static const char *mode_read_binary = "r";
-static const char *mode_write_binary = "w";
-static const char *mode_append_binary = "a";
-static const char *mode_read_text_plus = "r+";
-static const char *mode_write_text_plus = "w+";
-static const char *mode_append_text_plus = "a+";
-static const char *mode_read_binary_plus = "r+";
-static const char *mode_write_binary_plus = "w+";
-static const char *mode_append_binary_plus = "a+";
const char __gnat_text_translation_required = 0;
/* These functions do nothing in non-DOS systems. */
diff --git a/gcc/ada/terminals.c b/gcc/ada/terminals.c
new file mode 100644
index 00000000000..464e60a28aa
--- /dev/null
+++ b/gcc/ada/terminals.c
@@ -0,0 +1,1551 @@
+/****************************************************************************
+ * *
+ * GNAT RUN-TIME COMPONENTS *
+ * *
+ * T E R M I N A L S *
+ * *
+ * C Implementation File *
+ * *
+ * Copyright (C) 2008-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 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. *
+ * *
+ * 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. *
+ * *
+ ****************************************************************************/
+
+/* First all usupported platforms. Add stubs for exported routines. */
+
+#if defined (VMS) || defined (__vxworks) || defined (__Lynx__)
+
+void * __gnat_new_tty (void) { return (void*)0; }
+char * __gnat_tty_name (void* t) { return (char*)0; }
+int __gnat_interrupt_pid (int pid) { return -1; }
+int __gnat_interrupt_process (void* desc) { return -1; }
+int __gnat_setup_communication (void** desc) { return -1; }
+void __gnat_setup_parent_communication
+ (void* d, int* i, int* o, int*e, int*p) { return -1; }
+int __gnat_setup_child_communication
+ (void* d, char **n, int u) { return -1; }
+int __gnat_terminate_process (void *desc) { return -1; }
+int __gnat_tty_fd (void* t) { return -1; }
+int __gnat_tty_supported (void) { return 0; }
+int __gnat_tty_waitpid (void *desc) { return 1; }
+void __gnat_close_tty (void* t) {}
+void __gnat_free_process (void** process) {}
+void __gnat_reset_tty (void* t) {}
+void __gnat_send_header (void* d, char h[5], int s, int *r) {}
+void __gnat_setup_winsize (void *desc, int rows, int columns) {}
+
+/* For Windows platforms. */
+
+#elif defined(_WIN32)
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <windows.h>
+
+#define MAXPATHLEN 1024
+
+#define NILP(x) ((x) == 0)
+#define Qnil 0
+#define report_file_error(x, y) fprintf (stderr, "Error: %s\n", x);
+#define INTEGERP(x) 1
+#define XINT(x) x
+
+struct TTY_Process {
+ int pid; /* Number of this process */
+ PROCESS_INFORMATION procinfo;
+ HANDLE w_infd, w_outfd;
+ HANDLE w_forkin, w_forkout;
+ BOOL usePipe;
+};
+
+/* Control whether create_child cause the process to inherit GPS'
+ error mode setting. The default is 1, to minimize the possibility of
+ subprocesses blocking when accessing unmounted drives. */
+static int Vw32_start_process_inherit_error_mode = 1;
+
+/* Control whether spawnve quotes arguments as necessary to ensure
+ correct parsing by child process. Because not all uses of spawnve
+ are careful about constructing argv arrays, we make this behaviour
+ conditional (off by default, since a similar operation is already done
+ in g-expect.adb by calling Normalize_Argument). */
+static int Vw32_quote_process_args = 0;
+
+static DWORD AbsoluteSeek(HANDLE, DWORD);
+static VOID ReadBytes(HANDLE, LPVOID, DWORD);
+
+#define XFER_BUFFER_SIZE 2048
+
+/* This tell if the executable we're about to launch uses a GUI interface. */
+/* if we can't determine it, we will return true */
+static int
+is_gui_app (char *exe)
+{
+ HANDLE hImage;
+
+ DWORD bytes;
+ DWORD iSection;
+ DWORD SectionOffset;
+ DWORD CoffHeaderOffset;
+ DWORD MoreDosHeader[16];
+ CHAR *file;
+ size_t nlen;
+
+ ULONG ntSignature;
+
+ IMAGE_DOS_HEADER image_dos_header;
+ IMAGE_FILE_HEADER image_file_header;
+ IMAGE_OPTIONAL_HEADER image_optional_header;
+ IMAGE_SECTION_HEADER image_section_header;
+
+ /*
+ * Open the reference file.
+ */
+ nlen = strlen (exe);
+ file = exe;
+ if (nlen > 2) {
+ if (exe[0] == '"') {
+ /* remove quotes */
+ nlen -= 2;
+ file = malloc ((nlen + 1) * sizeof (char));
+ memcpy (file, &exe[1], nlen);
+ file [nlen] = '\0';
+ }
+ }
+ hImage = CreateFile(file,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (file != exe) {
+ free (file);
+ }
+
+ if (INVALID_HANDLE_VALUE == hImage)
+ {
+ report_file_error ("Could not open exe: ", Qnil);
+ report_file_error (exe, Qnil);
+ report_file_error ("\n", Qnil);
+ CloseHandle (hImage);
+ return -1;
+ }
+
+ /*
+ * Read the MS-DOS image header.
+ */
+ ReadBytes(hImage, &image_dos_header, sizeof(IMAGE_DOS_HEADER));
+
+ if (IMAGE_DOS_SIGNATURE != image_dos_header.e_magic)
+ {
+ report_file_error("Sorry, I do not understand this file.\n", Qnil);
+ CloseHandle (hImage);
+ return -1;
+ }
+
+ /*
+ * Read more MS-DOS header. */
+ ReadBytes(hImage, MoreDosHeader, sizeof(MoreDosHeader));
+ /*
+ * Get actual COFF header.
+ */
+ CoffHeaderOffset = AbsoluteSeek(hImage, image_dos_header.e_lfanew) +
+ sizeof(ULONG);
+ if (CoffHeaderOffset < 0) {
+ CloseHandle (hImage);
+ return -1;
+ }
+
+ ReadBytes (hImage, &ntSignature, sizeof(ULONG));
+
+ if (IMAGE_NT_SIGNATURE != ntSignature)
+ {
+ report_file_error ("Missing NT signature. Unknown file type.\n", Qnil);
+ CloseHandle (hImage);
+ return -1;
+ }
+
+ SectionOffset = CoffHeaderOffset + IMAGE_SIZEOF_FILE_HEADER +
+ IMAGE_SIZEOF_NT_OPTIONAL_HEADER;
+
+ ReadBytes(hImage, &image_file_header, IMAGE_SIZEOF_FILE_HEADER);
+
+ /*
+ * Read optional header.
+ */
+ ReadBytes(hImage,
+ &image_optional_header,
+ IMAGE_SIZEOF_NT_OPTIONAL_HEADER);
+
+ CloseHandle (hImage);
+
+ switch (image_optional_header.Subsystem)
+ {
+ case IMAGE_SUBSYSTEM_UNKNOWN:
+ return 1;
+ break;
+
+ case IMAGE_SUBSYSTEM_NATIVE:
+ return 1;
+ break;
+
+ case IMAGE_SUBSYSTEM_WINDOWS_GUI:
+ return 1;
+ break;
+
+ case IMAGE_SUBSYSTEM_WINDOWS_CUI:
+ return 0;
+ break;
+
+ case IMAGE_SUBSYSTEM_OS2_CUI:
+ return 0;
+ break;
+
+ case IMAGE_SUBSYSTEM_POSIX_CUI:
+ return 0;
+ break;
+
+ default:
+ /* Unknown, return GUI app to be preservative: if yes, it will be
+ correctly launched, if no, it will be launched, and a console will
+ be also displayed, which is not a big deal */
+ return 1;
+ break;
+ }
+
+}
+
+static DWORD
+AbsoluteSeek (HANDLE hFile, DWORD offset)
+{
+ DWORD newOffset;
+
+ newOffset = SetFilePointer (hFile, offset, NULL, FILE_BEGIN);
+
+ if (newOffset == 0xFFFFFFFF)
+ return -1;
+ else
+ return newOffset;
+}
+
+static VOID
+ReadBytes (HANDLE hFile, LPVOID buffer, DWORD size)
+{
+ DWORD bytes;
+
+ if (!ReadFile(hFile, buffer, size, &bytes, NULL))
+ {
+ size = 0;
+ return;
+ }
+ else if (size != bytes)
+ {
+ return;
+ }
+}
+
+static int
+nt_spawnve (char *exe, char **argv, char *env, struct TTY_Process *process)
+{
+ STARTUPINFO start;
+ SECURITY_ATTRIBUTES sec_attrs;
+ SECURITY_DESCRIPTOR sec_desc;
+ DWORD flags;
+ char dir[ MAXPATHLEN ];
+ int pid;
+ int is_gui, use_cmd;
+ char *cmdline, *parg, **targ;
+ int do_quoting = 0;
+ char escape_char;
+ int arglen;
+
+ /* we have to do some conjuring here to put argv and envp into the
+ form CreateProcess wants... argv needs to be a space separated/null
+ terminated list of parameters, and envp is a null
+ separated/double-null terminated list of parameters.
+
+ Additionally, zero-length args and args containing whitespace or
+ quote chars need to be wrapped in double quotes - for this to work,
+ embedded quotes need to be escaped as well. The aim is to ensure
+ the child process reconstructs the argv array we start with
+ exactly, so we treat quotes at the beginning and end of arguments
+ as embedded quotes.
+
+ Note that using backslash to escape embedded quotes requires
+ additional special handling if an embedded quote is already
+ preceeded by backslash, or if an arg requiring quoting ends with
+ backslash. In such cases, the run of escape characters needs to be
+ doubled. For consistency, we apply this special handling as long
+ as the escape character is not quote.
+
+ Since we have no idea how large argv and envp are likely to be we
+ figure out list lengths on the fly and allocate them. */
+
+ if (!NILP (Vw32_quote_process_args))
+ {
+ do_quoting = 1;
+ /* Override escape char by binding w32-quote-process-args to
+ desired character, or use t for auto-selection. */
+ if (INTEGERP (Vw32_quote_process_args))
+ escape_char = XINT (Vw32_quote_process_args);
+ else
+ escape_char = '\\';
+ }
+
+ /* do argv... */
+ arglen = 0;
+ targ = argv;
+ while (*targ)
+ {
+ char *p = *targ;
+ int need_quotes = 0;
+ int escape_char_run = 0;
+
+ if (*p == 0)
+ need_quotes = 1;
+ for ( ; *p; p++)
+ {
+ if (*p == '"')
+ {
+ /* allow for embedded quotes to be escaped */
+ arglen++;
+ need_quotes = 1;
+ /* handle the case where the embedded quote is already escaped */
+ if (escape_char_run > 0)
+ {
+ /* To preserve the arg exactly, we need to double the
+ preceding escape characters (plus adding one to
+ escape the quote character itself). */
+ arglen += escape_char_run;
+ }
+ }
+ else if (*p == ' ' || *p == '\t')
+ {
+ need_quotes = 1;
+ }
+
+ if (*p == escape_char && escape_char != '"')
+ escape_char_run++;
+ else
+ escape_char_run = 0;
+ }
+ if (need_quotes)
+ {
+ arglen += 2;
+ /* handle the case where the arg ends with an escape char - we
+ must not let the enclosing quote be escaped. */
+ if (escape_char_run > 0)
+ arglen += escape_char_run;
+ }
+ arglen += strlen (*targ) + 1;
+ targ++;
+ }
+
+ is_gui = is_gui_app (argv[0]);
+ use_cmd = FALSE;
+
+ if (is_gui == -1) {
+ /* could not determine application type. Try launching with "cmd /c" */
+ is_gui = FALSE;
+ arglen += 7;
+ use_cmd = TRUE;
+ }
+
+ cmdline = (char*)malloc (arglen + 1);
+ targ = argv;
+ parg = cmdline;
+
+ if (use_cmd == TRUE) {
+ strcpy (parg, "cmd /c ");
+ parg += 7;
+ }
+
+ while (*targ)
+ {
+ char * p = *targ;
+ int need_quotes = 0;
+
+ if (*p == 0)
+ need_quotes = 1;
+
+ if (do_quoting)
+ {
+ for ( ; *p; p++)
+ if (*p == ' ' || *p == '\t' || *p == '"')
+ need_quotes = 1;
+ }
+ if (need_quotes)
+ {
+ int escape_char_run = 0;
+ char * first;
+ char * last;
+
+ p = *targ;
+ first = p;
+ last = p + strlen (p) - 1;
+ *parg++ = '"';
+ for ( ; *p; p++)
+ {
+ if (*p == '"')
+ {
+ /* double preceding escape chars if any */
+ while (escape_char_run > 0)
+ {
+ *parg++ = escape_char;
+ escape_char_run--;
+ }
+ /* escape all quote chars, even at beginning or end */
+ *parg++ = escape_char;
+ }
+ *parg++ = *p;
+
+ if (*p == escape_char && escape_char != '"')
+ escape_char_run++;
+ else
+ escape_char_run = 0;
+ }
+ /* double escape chars before enclosing quote */
+ while (escape_char_run > 0)
+ {
+ *parg++ = escape_char;
+ escape_char_run--;
+ }
+ *parg++ = '"';
+ }
+ else
+ {
+ strcpy (parg, *targ);
+ parg += strlen (*targ);
+ }
+ *parg++ = ' ';
+ targ++;
+ }
+ *--parg = '\0';
+
+ memset (&start, 0, sizeof (start));
+ start.cb = sizeof (start);
+
+ if (process->usePipe == TRUE) {
+ start.dwFlags = STARTF_USESTDHANDLES;
+ start.hStdInput = process->w_forkin;
+ start.hStdOutput = process->w_forkout;
+ /* child's stderr is always redirected to outfd */
+ start.hStdError = process->w_forkout;
+ } else {
+ start.dwFlags = STARTF_USESTDHANDLES;
+ /* We only need to redirect stderr/stdout here. Stdin will be forced to
+ the spawned process console by explaunch */
+ start.hStdInput = NULL;
+ start.hStdOutput = process->w_forkout;
+ start.hStdError = process->w_forkout;
+ }
+
+ /* Explicitly specify no security */
+ if (!InitializeSecurityDescriptor (&sec_desc, SECURITY_DESCRIPTOR_REVISION))
+ goto EH_Fail;
+ if (!SetSecurityDescriptorDacl (&sec_desc, TRUE, NULL, FALSE))
+ goto EH_Fail;
+ sec_attrs.nLength = sizeof (sec_attrs);
+ sec_attrs.lpSecurityDescriptor = &sec_desc;
+ sec_attrs.bInheritHandle = FALSE;
+
+ /* creating a new console allow easier close. Do not use
+ CREATE_NEW_PROCESS_GROUP as this results in disabling Ctrl+C */
+ flags = CREATE_NEW_CONSOLE;
+ if (NILP (Vw32_start_process_inherit_error_mode))
+ flags |= CREATE_DEFAULT_ERROR_MODE;
+
+ /* if app is not a gui application, hide the console */
+ if (is_gui == FALSE) {
+ start.dwFlags |= STARTF_USESHOWWINDOW;
+ start.wShowWindow = SW_HIDE;
+ }
+
+ /* Set initial directory to null character to use current directory */
+ if (!CreateProcess (NULL, cmdline, &sec_attrs, NULL, TRUE,
+ flags, env, NULL, &start, &process->procinfo))
+ goto EH_Fail;
+
+ pid = (int) process->procinfo.hProcess;
+ process->pid=pid;
+
+ return pid;
+
+ EH_Fail:
+ return -1;
+}
+
+/*************************
+ ** __gnat_send_header ()
+ *************************/
+
+#define EXP_SLAVE_CREATE 'c'
+#define EXP_SLAVE_KEY 'k'
+#define EXP_SLAVE_MOUSE 'm'
+#define EXP_SLAVE_WRITE 'w'
+#define EXP_SLAVE_KILL 'x'
+
+#define EXP_KILL_TERMINATE 0x1
+#define EXP_KILL_CTRL_C 0x2
+#define EXP_KILL_CTRL_BREAK 0x4
+
+void
+__gnat_send_header (struct TTY_Process* p, char header[5], int size, int *ret)
+{
+ if (p->usePipe == FALSE) {
+ header[0] = EXP_SLAVE_WRITE;
+ header[1] = size & 0xff;
+ header[2] = (size & 0xff00) >> 8;
+ header[3] = (size & 0xff0000) >> 16;
+ header[4] = (size & 0xff000000) >> 24;
+ *ret = 1;
+ } else {
+ *ret = 0;
+ }
+}
+
+/**********************************
+ ** __gnat_setup_communication ()
+ **********************************/
+
+int
+__gnat_setup_communication (struct TTY_Process** process_out) /* output param */
+{
+ struct TTY_Process* process;
+
+ process = (struct TTY_Process*)malloc (sizeof (struct TTY_Process));
+ ZeroMemory (process, sizeof (struct TTY_Process));
+ *process_out = process;
+
+ return 0;
+}
+
+#define EXP_PIPE_BASENAME "\\\\.\\pipe\\ExpectPipe"
+
+int
+__gnat_setup_child_communication
+ (struct TTY_Process* process,
+ char** argv,
+ int Use_Pipes)
+{
+ int cpid;
+ HANDLE parent;
+ SECURITY_ATTRIBUTES sec_attrs;
+ char slavePath [MAX_PATH];
+ char **nargv;
+ int argc;
+ int i;
+ char pipeNameIn[100];
+ HANDLE hSlaveInDrv = NULL; /* Handle to communicate with slave driver */
+
+ parent = GetCurrentProcess ();
+
+ /* Set inheritance for the pipe handles */
+ sec_attrs.nLength = sizeof (SECURITY_ATTRIBUTES);
+ sec_attrs.bInheritHandle = TRUE;
+ sec_attrs.lpSecurityDescriptor = NULL;
+
+ if (Use_Pipes) {
+ /* Create in and out pipes */
+ if (!CreatePipe (&process->w_forkin, &process->w_infd, &sec_attrs, 0))
+ report_file_error ("Creation of child's IN handle", Qnil);
+ if (!CreatePipe (&process->w_outfd, &process->w_forkout, &sec_attrs, 0))
+ report_file_error ("Creation of child's OUT handle", Qnil);
+
+ /* Do not inherit the parent's side of the pipes */
+ SetHandleInformation (&process->w_infd, HANDLE_FLAG_INHERIT, 0);
+ SetHandleInformation (&process->w_outfd, HANDLE_FLAG_INHERIT, 0);
+
+ /* use native argv */
+ nargv = argv;
+ process->usePipe = TRUE;
+
+ } else {
+ static int pipeNameId = 0;
+
+ process->w_infd = NULL;
+
+ /* We create a named pipe for Input, as we handle input by sending special
+ commands to the explaunch process, that uses it to feed the actual input
+ of the process */
+ sprintf(pipeNameIn, "%sIn%08x_%08x", EXP_PIPE_BASENAME,
+ GetCurrentProcessId(), pipeNameId);
+ pipeNameId++;
+
+ hSlaveInDrv = CreateNamedPipe(pipeNameIn,
+ PIPE_ACCESS_OUTBOUND,
+ PIPE_TYPE_BYTE | PIPE_WAIT, 1, 8192, 8192,
+ 20000, NULL);
+ if (hSlaveInDrv == NULL) goto end;
+
+ if (!CreatePipe (&process->w_outfd, &process->w_forkout, &sec_attrs, 0))
+ report_file_error ("Creation of child's OUT handle", Qnil);
+
+ if (SearchPath (NULL, "explaunch.exe", NULL,
+ MAX_PATH, slavePath, NULL) == 0) goto end;
+
+ for (argc=0; argv[argc] != NULL; argc++) ;
+ nargv = (char **) malloc (sizeof (char*) * (argc + 3));
+ nargv[0] = slavePath;
+ nargv[1] = pipeNameIn;
+
+ for (i = 0; i <= argc; i++) nargv[i + 2] = argv[i];
+ process->usePipe = FALSE;
+ }
+
+ /* Spawn the child. */
+ cpid = nt_spawnve (nargv[0], nargv, NULL, process);
+
+ /* close the duplicated handles passed to the child */
+ CloseHandle (process->w_forkout);
+
+ if (process->usePipe == TRUE) {
+ CloseHandle (process->w_forkin);
+
+ } else {
+ UCHAR buf[8]; /* enough space for child status info */
+ DWORD count;
+ BOOL bRet;
+ DWORD dwRet;
+
+ /*
+ * Wait for connection with the slave driver
+ */
+ bRet = ConnectNamedPipe(hSlaveInDrv, NULL);
+ if (bRet == FALSE) {
+ dwRet = GetLastError();
+ if (dwRet == ERROR_PIPE_CONNECTED) {
+ ;
+ } else {
+ goto end;
+ }
+ }
+
+ process->w_infd = hSlaveInDrv;
+
+ /*
+ * wait for slave driver to initialize before allowing user to send to it
+ */
+ bRet = ReadFile(process->w_outfd, buf, 8, &count, NULL);
+ if (bRet == FALSE) {
+ cpid = -1;
+ }
+
+ dwRet = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
+ if (dwRet != 0) {
+ cpid = -1;
+ }
+
+ cpid = buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24);
+ process->pid = cpid;
+ }
+
+ if (cpid == -1)
+ /* An error occurred while trying to spawn the process. */
+ report_file_error ("Spawning child process", Qnil);
+
+ return cpid;
+ end:
+ if (hSlaveInDrv != NULL)
+ CloseHandle (hSlaveInDrv);
+ return -1;
+}
+
+void
+__gnat_setup_parent_communication
+ (struct TTY_Process* process,
+ int* in,
+ int* out,
+ int* err,
+ int* pid)
+{
+ *in = _open_osfhandle ((long) process->w_infd, 0);
+ *out = _open_osfhandle ((long) process->w_outfd, 0);
+ /* child's stderr is always redirected to outfd */
+ *err = *out;
+ *pid = process->pid;
+}
+
+typedef struct _child_process
+{
+ HWND hwnd;
+ PROCESS_INFORMATION *procinfo;
+} child_process;
+
+/* The major and minor versions of NT. */
+static int w32_major_version;
+static int w32_minor_version;
+
+/* Distinguish between Windows NT and Windows 95. */
+static enum {OS_UNKNOWN, OS_WIN95, OS_NT} os_subtype = OS_UNKNOWN;
+
+/* Cache information describing the NT system for later use. */
+static void
+cache_system_info (void)
+{
+ union
+ {
+ struct info
+ {
+ char major;
+ char minor;
+ short platform;
+ } info;
+ DWORD data;
+ } version;
+
+ /* Cache the version of the operating system. */
+ version.data = GetVersion ();
+ w32_major_version = version.info.major;
+ w32_minor_version = version.info.minor;
+
+ if (version.info.platform & 0x8000)
+ os_subtype = OS_WIN95;
+ else
+ os_subtype = OS_NT;
+}
+
+static BOOL CALLBACK
+find_child_console (HWND hwnd, child_process * cp)
+{
+ DWORD thread_id;
+ DWORD process_id;
+
+ thread_id = GetWindowThreadProcessId (hwnd, &process_id);
+ if (process_id == cp->procinfo->dwProcessId)
+ {
+ char window_class[32];
+
+ GetClassName (hwnd, window_class, sizeof (window_class));
+ if (strcmp (window_class,
+ (os_subtype == OS_WIN95)
+ ? "tty"
+ : "ConsoleWindowClass") == 0)
+ {
+ cp->hwnd = hwnd;
+ return FALSE;
+ }
+ }
+ /* keep looking */
+ return TRUE;
+}
+
+int
+__gnat_interrupt_process (struct TTY_Process* p)
+{
+ char buf[2];
+ DWORD written;
+ BOOL bret;
+
+ if (p->usePipe == TRUE) {
+ bret = FALSE;
+ } else {
+ buf[0] = EXP_SLAVE_KILL;
+ buf[1] = EXP_KILL_CTRL_C;
+ bret = WriteFile (p->w_infd, buf, 2, &written, NULL);
+ }
+
+ if (bret == FALSE) {
+ return __gnat_interrupt_pid (p->procinfo.dwProcessId);
+ }
+ return 0;
+}
+
+int
+__gnat_interrupt_pid (int pid)
+{
+ volatile child_process cp;
+ int rc = 0;
+
+ cp.procinfo = (LPPROCESS_INFORMATION) malloc (sizeof (PROCESS_INFORMATION));
+ cp.procinfo->dwProcessId = pid;
+
+ if (os_subtype == OS_UNKNOWN)
+ cache_system_info ();
+
+ /* Try to locate console window for process. */
+ EnumWindows ((WNDENUMPROC) find_child_console, (LPARAM) &cp);
+
+ if (cp.hwnd)
+ {
+ BYTE control_scan_code = (BYTE) MapVirtualKey (VK_CONTROL, 0);
+ /* Retrieve Ctrl-C scancode */
+ BYTE vk_break_code = 'C';
+ BYTE break_scan_code = (BYTE) MapVirtualKey (vk_break_code, 0);
+ HWND foreground_window;
+
+ foreground_window = GetForegroundWindow ();
+ if (foreground_window)
+ {
+ /* NT 5.0, and apparently also Windows 98, will not allow
+ a Window to be set to foreground directly without the
+ user's involvement. The workaround is to attach
+ ourselves to the thread that owns the foreground
+ window, since that is the only thread that can set the
+ foreground window. */
+ DWORD foreground_thread, child_thread;
+
+ foreground_thread =
+ GetWindowThreadProcessId (foreground_window, NULL);
+ if (foreground_thread == GetCurrentThreadId ()
+ || !AttachThreadInput (GetCurrentThreadId (),
+ foreground_thread, TRUE))
+ foreground_thread = 0;
+
+ child_thread = GetWindowThreadProcessId (cp.hwnd, NULL);
+ if (child_thread == GetCurrentThreadId ()
+ || !AttachThreadInput (GetCurrentThreadId (),
+ child_thread, TRUE))
+ child_thread = 0;
+
+ /* Set the foreground window to the child. */
+ if (SetForegroundWindow (cp.hwnd))
+ {
+ /* Generate keystrokes as if user had typed Ctrl-Break or
+ Ctrl-C. */
+ keybd_event (VK_CONTROL, control_scan_code, 0, 0);
+ keybd_event (vk_break_code, break_scan_code,
+ (vk_break_code == 'C' ? 0 : KEYEVENTF_EXTENDEDKEY), 0);
+ keybd_event (vk_break_code, break_scan_code,
+ (vk_break_code == 'C' ? 0 : KEYEVENTF_EXTENDEDKEY)
+ | KEYEVENTF_KEYUP, 0);
+ keybd_event (VK_CONTROL, control_scan_code, KEYEVENTF_KEYUP, 0);
+
+ /* Sleep for a bit to give time for the main frame to respond
+ to focus change events. */
+ Sleep (100);
+
+ SetForegroundWindow (foreground_window);
+ }
+ /* Detach from the foreground and child threads now that
+ the foreground switching is over. */
+ if (foreground_thread)
+ AttachThreadInput (GetCurrentThreadId (), foreground_thread, FALSE);
+ if (child_thread)
+ AttachThreadInput (GetCurrentThreadId (), child_thread, FALSE);
+ }
+ }
+ /* Ctrl-Break is NT equivalent of SIGINT. */
+ else if (!GenerateConsoleCtrlEvent
+ (CTRL_BREAK_EVENT, cp.procinfo->dwProcessId))
+ {
+ errno = EINVAL;
+ rc = -1;
+ }
+
+ free (cp.procinfo);
+ return rc;
+}
+
+/* kill a process, as this implementation use CreateProcess on Win32 we need
+ to use Win32 TerminateProcess API */
+int
+__gnat_terminate_process (struct TTY_Process* p)
+{
+ char buf[2];
+ DWORD written;
+ BOOL bret;
+
+ if (p->usePipe == TRUE) {
+ bret = FALSE;
+ } else {
+ buf[0] = EXP_SLAVE_KILL;
+ buf[1] = EXP_KILL_TERMINATE;
+ bret = WriteFile (p->w_infd, buf, 2, &written, NULL);
+ }
+
+ if (bret == FALSE) {
+ if (!TerminateProcess (p->procinfo.hProcess, 1))
+ return -1;
+ else
+ return 0;
+ } else
+ return 0;
+}
+
+/* wait for process pid to terminate and return the process status. This
+ implementation is different from the adaint.c one for Windows as it uses
+ the Win32 API instead of the C one. */
+
+int
+__gnat_tty_waitpid (struct TTY_Process* p)
+{
+ DWORD exitcode;
+ DWORD res;
+ HANDLE proc_hand = p->procinfo.hProcess;
+
+ res = WaitForSingleObject (proc_hand, 0);
+ GetExitCodeProcess (proc_hand, &exitcode);
+
+ CloseHandle (p->procinfo.hThread);
+ CloseHandle (p->procinfo.hProcess);
+
+ /* No need to close the handles: they were closed on the ada side */
+
+ return (int) exitcode;
+}
+
+/********************************
+ ** __gnat_free_process ()
+ ********************************/
+
+void
+__gnat_free_process (struct TTY_Process** process)
+{
+ free (*process);
+ *process = NULL;
+}
+
+/* TTY handling */
+
+typedef struct {
+ int tty_fd; /* descriptor for the tty */
+ char tty_name[24]; /* Name of TTY device */
+} TTY_Handle;
+
+int
+__gnat_tty_supported (void)
+{
+ return 0;
+}
+
+/* Return the tty name associated with p */
+
+char *
+__gnat_tty_name (TTY_Handle* t)
+{
+ return t->tty_name;
+}
+
+int
+__gnat_tty_fd (TTY_Handle* t)
+{
+ return t->tty_fd;
+}
+
+TTY_Handle*
+__gnat_new_tty (void)
+{
+ return (TTY_Handle*)0;
+}
+
+void
+__gnat_reset_tty (TTY_Handle* t)
+{
+ return;
+}
+
+void
+__gnat_close_tty (TTY_Handle* t)
+{
+ free (t);
+}
+
+void
+__gnat_setup_winsize (void *desc, int rows, int columns)
+{
+}
+
+#else /* defined(_WIN32, implementatin for all UNIXes */
+
+/* First defined some macro to identify easily some systems */
+#if defined (__FreeBSD__) \
+ || defined (__OpenBSD__) \
+ || defined (__NetBSD__) \
+ || defined (__DragonFly__)
+# define FREEBSD
+#endif
+#if defined (__alpha__) && defined (__osf__)
+# define OSF1
+#endif
+#if defined (__mips) && defined (__sgi)
+# define IRIX
+#endif
+
+/* Include every system header we need */
+#define _GNU_SOURCE
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* On some system termio is either absent or including it will disable termios
+ (HP-UX) */
+#if ! defined (__hpux__) && ! defined (FREEBSD) && ! defined (__APPLE__)
+# include <termio.h>
+#endif
+
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#if defined (sun)
+# include <sys/stropts.h>
+#endif
+#if defined (FREEBSD) || defined (sun)
+# include <sys/signal.h>
+#endif
+#if defined (__hpux__)
+# include <sys/termio.h>
+# include <sys/stropts.h>
+#endif
+
+#define CDISABLE _POSIX_VDISABLE
+
+/* On HP-UX and Sun system, there is a bzero function but with a different
+ signature. Use memset instead */
+#if defined (__hpux__) || defined (sun) || defined (_AIX)
+# define bzero(s,n) memset (s,0,n)
+#endif
+
+/* POSIX does not specify how to open the master side of a terminal.Several
+ methods are available (system specific):
+ 1- using a cloning device (USE_CLONE_DEVICE)
+ 2- getpt (USE_GETPT)
+ 3- openpty (USE_OPENPTY)
+ 4- _getpty (USE_GETPTY)
+
+ When using the cloning device method, the macro USE_CLONE_DEVICE should
+ contains a full path to the adequate device.
+
+ When a new system is about to be supported, one of the previous macro should
+ be set otherwise allocate_pty_desc will return an error
+*/
+
+/* Configurable part */
+#if defined (__APPLE__) || defined (FREEBSD)
+#define USE_OPENPTY
+#elif defined (IRIX)
+#define USE_GETPTY
+#elif defined (linux)
+#define USE_GETPT
+#elif defined (sun)
+#define USE_CLONE_DEVICE "/dev/ptmx"
+#elif defined (_AIX)
+#define USE_CLONE_DEVICE "/dev/ptc"
+#elif defined (OSF1)
+/* On Tru64, the systems offers various interfaces to open a terminal:
+ - /dev/ptmx: this the system V driver (stream based),
+ - /dev/ptmx_bsd: the non stream based clone device,
+ - the openpty function which use BSD interface.
+
+ Using directly /dev/ptmx_bsd on Tru64 5.1B seems to consume all the
+ available slave ptys (why ?). When using openpty it seems that the function
+ handles the creation of entries in /dev/pts when necessary and so avoid this
+ starvation issue. The pty man entry suggests also to use openpty.
+*/
+#define USE_OPENPTY
+#elif defined (__hpux__)
+/* On HP-UX we use the streamed version. Using the non streamed version is not
+ recommanded (through "/dev/ptym/clone"). Indeed it seems that there are
+ issues to detect process terminations. */
+#define USE_CLONE_DEVICE "/dev/ptmx"
+#endif
+
+/* structure that holds information about the terminal used and the process
+ connected on the slave side */
+typedef struct pty_desc_struct {
+ int master_fd; /* fd of the master side if the terminal */
+ int slave_fd; /* fd of the slave side */
+ char slave_name[32]; /* filename of the slave side */
+ int child_pid; /* PID of the child process connected to the slave side
+ of the terminal */
+} pty_desc;
+
+/* allocate_pty_desc - allocate a pseudo terminal
+ *
+ * PARAMETERS
+ * out desc returned pointer to a pty_desc structure containing information
+ * about the opened pseudo terminal
+ * RETURN VALUE
+ * -1 if failed
+ * 0 if ok
+ * COMMENTS
+ * If the function is successful we should have at least the master side fd
+ * and the slave side filename. On some system, the slave side will also be
+ * opened. If this is not the case the slave side will be open once we are in
+ * the child process (note that opening the slave side at this stage will
+ * failed...).
+ */
+
+extern char* ptsname (int);
+
+static int
+allocate_pty_desc (pty_desc **desc) {
+
+ pty_desc *result;
+ int status = 0;
+ int slave_fd = -1;
+ int master_fd = -1;
+ char *slave_name = NULL;
+
+#ifdef USE_GETPT
+ master_fd = getpt ();
+#elif defined (USE_OPENPTY)
+ status = openpty (&master_fd, &slave_fd, NULL, NULL, NULL);
+#elif defined (USE_GETPTY)
+ slave_name = _getpty (&master_fd, O_RDWR | O_NDELAY, 0600, 0);
+ if (slave_name == NULL) status = -1;
+#elif defined (USE_CLONE_DEVICE)
+ master_fd = open (USE_CLONE_DEVICE, O_RDWR | O_NONBLOCK, 0);
+#else
+ printf ("[error]: terminal support is not configured\n");
+ return -1;
+#endif
+
+ /* at this stage we should have the master side fd and status should be 0 */
+ if (status != 0 || master_fd < 0)
+ {
+ /* If this is not the case close all opened files and return -1 */
+ printf ("[error]: cannot allocate master side of the pty\n");
+ if (master_fd >= 0) close (master_fd);
+ if (slave_fd >= 0) close (slave_fd);
+ *desc = NULL;
+ return -1;
+ }
+
+ /* retrieve the file name of the slave side if necessary */
+ if (slave_name == NULL) slave_name = (char *) ptsname (master_fd);
+
+ /* Now we should have slave file name */
+ if (slave_name == NULL)
+ {
+ /* If not the case close any opened file and return - 1 */
+ printf ("[error]: cannot allocate slave side of the pty\n");
+ if (master_fd >= 0) close (master_fd);
+ if (slave_fd >= 0) close (slave_fd);
+ *desc = NULL;
+ return -1;
+ }
+
+ /* grant access to the slave side */
+ grantpt (master_fd);
+ /* unlock the terminal */
+ unlockpt (master_fd);
+
+ /* set desc and return 0 */
+ result = malloc (sizeof (pty_desc));
+ result->master_fd = master_fd;
+ result->slave_fd = slave_fd;
+ /* the string returned by ptsname or _getpty is a static allocated string. So
+ we should make a copy */
+ strncpy (result->slave_name, slave_name, sizeof (result->slave_name));
+ result->slave_name[sizeof (result->slave_name) - 1] = '\0';
+ result->child_pid = -1;
+ *desc=result;
+ return 0;
+}
+
+/* some utility macro that make the code of child_setup_tty easier to read */
+#define __enable(a, b) ((a) |= (b))
+#define __disable(a, b) ((a) &= ~(b))
+
+/* some properties do not exist on all systems. Set their value to 0 in that
+ case */
+#ifndef IUCLC
+#define IUCLC 0
+#endif
+#ifndef OLCUC
+#define OLCUC 0
+#endif
+#ifndef NLDLY
+#define NLDLY 0
+#define CRDLY 0
+#define TABDLY 0
+#define BSDLY 0
+#define VTDLY 0
+#define FFDLY 0
+#endif
+
+/* child_setup_tty - set terminal properties
+ *
+ * PARAMETERS
+ * file descriptor of the slave side of the terminal
+ *
+ * RETURN VALUE
+ * 0 if success, any other value if failed.
+ *
+ * COMMENTS
+ * None
+ */
+static int
+child_setup_tty (int fd)
+{
+ struct termios s;
+ int status;
+
+ /* ensure that s is filled with 0 */
+ bzero (&s, sizeof (&s));
+
+ /* Get the current terminal settings */
+ status = tcgetattr (fd, &s);
+ if (status != 0) return -1;
+
+ /* Adjust input modes */
+ __disable (s.c_iflag, IUCLC); /* don't transform to lower case */
+ __disable (s.c_iflag, ISTRIP); /* don't delete 8th bit */
+
+ /* Adjust output modes */
+ __enable (s.c_oflag, OPOST); /* enable postprocessing */
+ __disable (s.c_oflag, ONLCR); /* don't map LF to CR-LF */
+ __disable (s.c_oflag, NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
+ /* disable delays */
+ __disable (s.c_oflag, OLCUC); /* don't transform to upper case */
+
+ /* Adjust control modes */
+ s.c_cflag = (s.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
+
+ /* Adjust local modes */
+ __disable (s.c_lflag, ECHO); /* disable echo */
+ __enable (s.c_lflag, ISIG); /* enable signals */
+ __enable (s.c_lflag, ICANON); /* erase/kill/eof processing */
+
+ /* Adjust control characters */
+ /* IMPORTANT: we need to ensure that Ctrl-C will trigger an interrupt signal
+ otherwise send_signal_via_characters will fail */
+ s.c_cc[VEOF] = 04; /* insure that EOF is Control-D */
+ s.c_cc[VERASE] = CDISABLE; /* disable erase processing */
+ s.c_cc[VKILL] = CDISABLE; /* disable kill processing */
+ s.c_cc[VQUIT] = 28; /* Control-\ */
+ s.c_cc[VINTR] = 03; /* Control-C */
+ s.c_cc[VEOL] = CDISABLE;
+ s.c_cc[VSUSP] = 26; /* Control-Z */
+
+ /* push our changes */
+ status = tcsetattr (fd, TCSADRAIN, &s);
+ return status;
+}
+
+/* __gnat_setup_communication - interface to the external world. Should be
+ * called before forking. On Unixes this function only call allocate_pty_desc.
+ * The Windows implementation (in different part of this file) is very
+ * different.
+ *
+ * PARAMETERS
+ * out desc returned pointer to a pty_desc structure
+ * RETURN VALUE
+ * 0 if success, -1 otherwise
+ */
+int __gnat_setup_communication (pty_desc** desc) {
+ return allocate_pty_desc (desc);
+}
+
+/* __gnat_setup_parent_communication - interface to the external world. Should
+ * be called after forking in the parent process
+ *
+ * PARAMETERS
+ * out in_fd
+ out out_fd
+ out err_fd fds corresponding to the parent side of the
+ terminal
+ in pid_out child process pid
+ * RETRUN VALUE
+ * 0
+ */
+void
+__gnat_setup_parent_communication
+ (pty_desc *desc,
+ int* in_fd, /* input */
+ int* out_fd, /* output */
+ int* err_fd, /* error */
+ int* pid_out)
+{
+
+ *in_fd = desc->master_fd;
+ *out_fd= desc->master_fd;
+ *err_fd= desc->master_fd;
+ desc->child_pid = *pid_out;
+}
+
+/* __gnat_setup_winsize - Sets up the size of the terminal
+ * This lets the process know the size of the terminal
+ */
+
+void __gnat_setup_winsize (pty_desc *desc, int rows, int columns) {
+#ifdef TIOCGWINSZ
+ struct winsize s;
+ s.ws_row = (unsigned short)rows;
+ s.ws_col = (unsigned short)columns;
+ s.ws_xpixel = 0;
+ s.ws_ypixel = 0;
+ ioctl (desc->master_fd, TIOCSWINSZ, &s);
+#ifdef SIGWINCH
+ if (desc->child_pid > 0) {
+ /* Let the process know about the change in size */
+ kill (desc->child_pid, SIGWINCH);
+ }
+#endif
+#endif
+}
+
+/* __gnat_setup_child_communication - interface to external world. Should be
+ * called after forking in the child process. On Unixes, this function
+ * first adjust the line setting, set standard output, input and error and
+ * then spawn the program.
+ *
+ * PARAMETERS
+ * desc a pty_desc structure containing the pty parameters
+ * new_argv argv of the program to be spawned
+ * RETURN VALUE
+ * this function should not return
+ */
+int
+__gnat_setup_child_communication
+ (pty_desc *desc,
+ char **new_argv,
+ int Use_Pipes)
+{
+ int status;
+ int pid = getpid ();
+
+ setsid ();
+
+ /* open the slave side of the terminal if necessary */
+ if (desc->slave_fd == -1)
+#if defined (_AIX)
+ /* On AIX, if the slave process is not opened with O_NDELAY or O_NONBLOCK
+ then we might have some processes hanging on I/O system calls. Not sure
+ we can do that for all platforms so do it only on AIX for the moment.
+ On AIX O_NONBLOCK and O_NDELAY have slightly different meanings. When
+ reading on the slave fd, in case there is no data available, if O_NDELAY
+ is set then 0 is returned. If O_NON_BLOCK is -1 is returned. It seems
+ that interactive programs such as GDB prefer the O_NDELAY behavior.
+ We chose O_NONBLOCK because it allows us to make the distinction
+ between a true EOF and an EOF returned because there is no data
+ available to be read. */
+ desc->slave_fd = open (desc->slave_name, O_RDWR | O_NONBLOCK, 0);
+#else
+ desc->slave_fd = open (desc->slave_name, O_RDWR, 0);
+#endif
+
+#if defined (sun) || defined (__hpux__)
+ /* On systems such as Solaris we are using stream. We need to push the right
+ "modules" in order to get the expected terminal behaviors. Otherwise
+ functionalities such as termios are not available. */
+ ioctl (desc->slave_fd, I_PUSH, "ptem");
+ ioctl (desc->slave_fd, I_PUSH, "ldterm");
+ ioctl (desc->slave_fd, I_PUSH, "ttcompat");
+#endif
+
+#ifdef TIOCSCTTY
+ /* make the tty the controling terminal */
+ status = ioctl (desc->slave_fd, TIOCSCTTY, 0);
+#endif
+
+ /* adjust tty settings */
+ child_setup_tty (desc->slave_fd);
+ __gnat_setup_winsize (desc, 24, 80); /* To prevent errors in some shells */
+
+ /* stdin, stdout and stderr should be now our tty */
+ dup2 (desc->slave_fd, 0);
+ dup2 (desc->slave_fd, 1);
+ dup2 (desc->slave_fd, 2);
+ if (desc->slave_fd > 2) close (desc->slave_fd);
+
+ /* adjust process group settings */
+ status = setpgid (pid, pid);
+ status = tcsetpgrp (0, pid);
+
+ /* launch the program */
+ execvp (new_argv[0], new_argv);
+
+ /* return the pid */
+ return pid;
+}
+
+/* send_signal_via_characters - Send a characters that will trigger a signal
+ * in the child process.
+ *
+ * PARAMETERS
+ * desc a pty_desc structure containing terminal information
+ * int a signal number
+ * RETURN VALUE
+ * None
+ */
+static void
+send_signal_via_characters
+ (pty_desc *desc,
+ int signal_number)
+{
+ char ctrl_c = 03;
+ char ctrl_backslash = 28;
+ char ctrl_Z = 26;
+
+ switch (signal_number)
+ {
+ case SIGINT:
+ write (desc->master_fd, &ctrl_c, 1); return;
+ case SIGQUIT:
+ write (desc->master_fd, &ctrl_backslash, 1); return;
+ case SIGTSTP:
+ write (desc->master_fd, &ctrl_Z, 1); return;
+ }
+}
+
+/* __gnat_interrupt_process - interrupt the child process
+ *
+ * PARAMETERS
+ * desc a pty_desc structure
+ */
+int
+__gnat_interrupt_process (pty_desc *desc)
+{
+ send_signal_via_characters (desc, SIGINT);
+ return 0;
+}
+
+/* __gnat_interrupt_pid - interrupt a process group
+ *
+ * PARAMETERS
+ * pid pid of the process to interrupt
+ */
+int
+__gnat_interrupt_pid (int pid)
+{
+ kill (-pid, SIGINT);
+ return 0;
+}
+
+/* __gnat_terminate_process - kill a child process
+ *
+ * PARAMETERS
+ * desc pty_desc structure
+ */
+int __gnat_terminate_process (pty_desc *desc)
+{
+ return kill (desc->child_pid, SIGKILL);
+}
+
+/* __gnat_tty_waitpid - wait for the child proces to die
+ *
+ * PARAMETERS
+ * desc pty_desc structure
+ * RETURN VALUE
+ * exit status of the child process
+ */
+int
+__gnat_tty_waitpid (pty_desc *desc)
+{
+ int status = 0;
+ waitpid (desc->child_pid, &status, 0);
+ return WEXITSTATUS (status);
+}
+
+/* __gnat_tty_supported - Are tty supported ?
+ *
+ * RETURN VALUE
+ * always 1 on Unix systems
+ */
+int
+__gnat_tty_supported (void)
+{
+ return 1;
+}
+
+/* __gnat_free_process - free a pty_desc structure
+ *
+ * PARAMETERS
+ * in out desc: a pty desc structure
+ */
+void
+__gnat_free_process (pty_desc** desc)
+{
+ free (*desc);
+ *desc = NULL;
+}
+
+/* __gnat_send_header - dummy function. this interface is only used on Windows */
+void
+__gnat_send_header (pty_desc* desc, char header[5], int size, int *ret)
+{
+ *ret = 0;
+}
+
+/* __gnat_reset_tty - reset line setting
+ *
+ * PARAMETERS
+ * desc: a pty_desc structure
+ */
+void
+__gnat_reset_tty (pty_desc* desc)
+{
+ child_setup_tty (desc->master_fd);
+}
+
+/* __gnat_new_tty - allocate a new terminal
+ *
+ * RETURN VALUE
+ * a pty_desc structure
+ */
+pty_desc *
+__gnat_new_tty (void)
+{
+ int status;
+ pty_desc* desc;
+ status = allocate_pty_desc (&desc);
+ child_setup_tty (desc->master_fd);
+ return desc;
+}
+
+/* __gnat_close_tty - close a terminal
+ *
+ * PARAMETERS
+ * desc a pty_desc strucure
+ */
+void __gnat_close_tty (pty_desc* desc)
+{
+ if (desc->master_fd >= 0) close (desc->master_fd);
+ if (desc->slave_fd >= 0) close (desc->slave_fd);
+}
+
+/* __gnat_tty_name - return slave side device name
+ *
+ * PARAMETERS
+ * desc a pty_desc strucure
+ * RETURN VALUE
+ * a string
+ */
+char *
+__gnat_tty_name (pty_desc* desc)
+{
+ return desc->slave_name;
+}
+
+/* __gnat_tty_name - return master side fd
+ *
+ * PARAMETERS
+ * desc a pty_desc strucure
+ * RETURN VALUE
+ * a fd
+ */
+int
+__gnat_tty_fd (pty_desc* desc)
+{
+ return desc->master_fd;
+}
+
+#endif /* WIN32 */
diff --git a/gcc/ada/thread.c b/gcc/ada/thread.c
new file mode 100644
index 00000000000..a55accefef0
--- /dev/null
+++ b/gcc/ada/thread.c
@@ -0,0 +1,57 @@
+/****************************************************************************
+ * *
+ * GNAT COMPILER COMPONENTS *
+ * *
+ * P T H R E A D *
+ * *
+ * C 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. *
+ * *
+ * 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. *
+ * *
+ ****************************************************************************/
+
+/* This file provides utility functions to access the threads API */
+
+#include "s-oscons.h"
+
+#ifdef NEED_PTHREAD_CONDATTR_SETCLOCK
+# include <pthread.h>
+# include <time.h>
+
+int
+__gnat_pthread_condattr_setup(pthread_condattr_t *attr) {
+/*
+ * If using a clock other than CLOCK_REALTIME for the Ada Monotonic_Clock,
+ * the corresponding clock id must be set for condition variables.
+ */
+ return pthread_condattr_setclock (attr, CLOCK_RT_Ada);
+}
+
+#else
+
+int
+__gnat_pthread_condattr_setup (void *attr) {
+ /* Dummy version for other platforms, which may or may not have pthread.h */
+ return 0;
+}
+
+#endif
diff --git a/gcc/ada/types.ads b/gcc/ada/types.ads
index 05d3dbe1b9d..75a910d3301 100644
--- a/gcc/ada/types.ads
+++ b/gcc/ada/types.ads
@@ -102,12 +102,8 @@ package Types is
-- Graphic characters, as defined in ARM
subtype Line_Terminator is Character range ASCII.LF .. ASCII.CR;
- -- Line terminator characters (LF, VT, FF, CR)
- --
- -- This definition is dubious now that we have two more wide character
- -- sequences that constitute a line terminator. Every reference to this
- -- subtype needs checking to make sure the wide character case is handled
- -- appropriately. ???
+ -- Line terminator characters (LF, VT, FF, CR). For further details,
+ -- see the extensive discussion of line termination in the Sinput spec.
subtype Upper_Half_Character is
Character range Character'Val (16#80#) .. Character'Val (16#FF#);
diff --git a/gcc/ada/vms_data.ads b/gcc/ada/vms_data.ads
index bfda0a73c56..9fc3d97d2e2 100644
--- a/gcc/ada/vms_data.ads
+++ b/gcc/ada/vms_data.ads
@@ -6200,6 +6200,14 @@ package VMS_Data is
--
-- Set the maximum line length, nnn from 32 ..256. The default is 79.
+ S_Pretty_Maxact : aliased constant S := "/MAX_ACT=#" &
+ "--call_threshold=#";
+ -- /MAX_ACT=nnn
+ --
+ -- If the number of parameter associations is greater than nnn and if at
+ -- least one association uses named notation, start each association from
+ -- a new line
+
S_Pretty_Maxind : aliased constant S := "/MAX_INDENT=#" &
"-T#";
-- /MAX_INDENT=nnn
@@ -6209,6 +6217,14 @@ package VMS_Data is
-- If nnn is zero, an additional indentation level is used for any
-- number of case alternatives and variants.
+ S_Pretty_Maxpar : aliased constant S := "/MAX_PAR=#" &
+ "--par_threshold=#";
+ -- /MAX_PAR=nnn
+ --
+ -- If the number of parameter specifications is greater than nnn (or equal
+ -- to nnn in case of a function), start each specification from a new line.
+ -- The default value is 3.
+
S_Pretty_Mess : aliased constant S := "/MESSAGES_PROJECT_FILE=" &
"DEFAULT " &
"-vP0 " &
@@ -6361,6 +6377,30 @@ package VMS_Data is
-- of the directory specified in the project file. If the subdirectory
-- does not exist, it is created automatically.
+ S_Pretty_Types : aliased constant S := "/TYPE_CASING=" &
+ "AS_DECLARED " &
+ "-ntD " &
+ "LOWER_CASE " &
+ "-ntL " &
+ "UPPER_CASE " &
+ "-ntU " &
+ "MIXED_CASE " &
+ "-ntM";
+ -- /TYPE_CASING=name-option
+ --
+ -- Specify the casing of type and subtype. If not specified, the
+ -- casing of these names is defined by the NAME_CASING option.
+ -- 'name-option' may be one of:
+ --
+ -- AS_DECLARED Name casing for defining occurrences are
+ -- as they appear in the source file.
+ --
+ -- LOWER_CASE Namess are in lower case.
+ --
+ -- UPPER_CASE Namess are in upper case.
+ --
+ -- MIXED_CASE Namess are in mixed case.
+
S_Pretty_Verbose : aliased constant S := "/VERBOSE " &
"-v";
-- /NOVERBOSE (D)
@@ -6401,7 +6441,9 @@ package VMS_Data is
S_Pretty_Indent 'Access,
S_Pretty_Keyword 'Access,
S_Pretty_Maxlen 'Access,
+ S_Pretty_Maxact 'Access,
S_Pretty_Maxind 'Access,
+ S_Pretty_Maxpar 'Access,
S_Pretty_Mess 'Access,
S_Pretty_Names 'Access,
S_Pretty_No_Labels 'Access,
@@ -6422,6 +6464,7 @@ package VMS_Data is
S_Pretty_Stnm_On_Nw_Line 'Access,
S_Pretty_Specific 'Access,
S_Pretty_Standard 'Access,
+ S_Pretty_Types 'Access,
S_Pretty_Verbose 'Access,
S_Pretty_Warnings 'Access);
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 9dc68cc341f..5ad69ceca92 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -227,7 +227,7 @@ static void expand_builtin_sync_synchronize (void);
/* Return true if NAME starts with __builtin_ or __sync_. */
-bool
+static bool
is_builtin_name (const char *name)
{
if (strncmp (name, "__builtin_", 10) == 0)
@@ -5227,7 +5227,7 @@ expand_builtin_sync_lock_test_and_set (enum machine_mode mode, tree exp,
mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
- return expand_atomic_exchange (target, mem, val, MEMMODEL_ACQUIRE, true);
+ return expand_sync_lock_test_and_set (target, mem, val);
}
/* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */
@@ -5291,7 +5291,7 @@ expand_builtin_atomic_exchange (enum machine_mode mode, tree exp, rtx target)
mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
- return expand_atomic_exchange (target, mem, val, model, false);
+ return expand_atomic_exchange (target, mem, val, model);
}
/* Expand the __atomic_compare_exchange intrinsic:
@@ -5482,6 +5482,11 @@ expand_builtin_atomic_fetch_op (enum machine_mode mode, tree exp, rtx target,
}
+#ifndef HAVE_atomic_clear
+# define HAVE_atomic_clear 0
+# define gen_atomic_clear(x,y) (gcc_unreachable (), NULL_RTX)
+#endif
+
/* Expand an atomic clear operation.
void _atomic_clear (BOOL *obj, enum memmodel)
EXP is the call expression. */
@@ -5503,6 +5508,12 @@ expand_builtin_atomic_clear (tree exp)
return const0_rtx;
}
+ if (HAVE_atomic_clear)
+ {
+ emit_insn (gen_atomic_clear (mem, model));
+ return const0_rtx;
+ }
+
/* Try issuing an __atomic_store, and allow fallback to __sync_lock_release.
Failing that, a store is issued by __atomic_store. The only way this can
fail is if the bool type is larger than a word size. Unlikely, but
@@ -5519,9 +5530,9 @@ expand_builtin_atomic_clear (tree exp)
EXP is the call expression. */
static rtx
-expand_builtin_atomic_test_and_set (tree exp)
+expand_builtin_atomic_test_and_set (tree exp, rtx target)
{
- rtx mem, ret;
+ rtx mem;
enum memmodel model;
enum machine_mode mode;
@@ -5529,20 +5540,7 @@ expand_builtin_atomic_test_and_set (tree exp)
mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
model = get_memmodel (CALL_EXPR_ARG (exp, 1));
- /* Try issuing an exchange. If it is lock free, or if there is a limited
- functionality __sync_lock_test_and_set, this will utilize it. */
- ret = expand_atomic_exchange (NULL_RTX, mem, const1_rtx, model, true);
- if (ret)
- return ret;
-
- /* Otherwise, there is no lock free support for test and set. Simply
- perform a load and a store. Since this presumes a non-atomic architecture,
- also assume single threadedness and don't issue barriers either. */
-
- ret = gen_reg_rtx (mode);
- emit_move_insn (ret, mem);
- emit_move_insn (mem, const1_rtx);
- return ret;
+ return expand_atomic_test_and_set (target, mem, model);
}
@@ -5672,23 +5670,6 @@ expand_builtin_atomic_is_lock_free (tree exp)
return NULL_RTX;
}
-/* This routine will either emit the mem_thread_fence pattern or issue a
- sync_synchronize to generate a fence for memory model MEMMODEL. */
-
-#ifndef HAVE_mem_thread_fence
-# define HAVE_mem_thread_fence 0
-# define gen_mem_thread_fence(x) (gcc_unreachable (), NULL_RTX)
-#endif
-
-void
-expand_builtin_mem_thread_fence (enum memmodel model)
-{
- if (HAVE_mem_thread_fence)
- emit_insn (gen_mem_thread_fence (GEN_INT (model)));
- else if (model != MEMMODEL_RELAXED)
- expand_builtin_sync_synchronize ();
-}
-
/* Expand the __atomic_thread_fence intrinsic:
void __atomic_thread_fence (enum memmodel)
EXP is the CALL_EXPR. */
@@ -5696,46 +5677,8 @@ expand_builtin_mem_thread_fence (enum memmodel model)
static void
expand_builtin_atomic_thread_fence (tree exp)
{
- enum memmodel model;
-
- model = get_memmodel (CALL_EXPR_ARG (exp, 0));
- expand_builtin_mem_thread_fence (model);
-}
-
-/* This routine will either emit the mem_signal_fence pattern or issue a
- sync_synchronize to generate a fence for memory model MEMMODEL. */
-
-#ifndef HAVE_mem_signal_fence
-# define HAVE_mem_signal_fence 0
-# define gen_mem_signal_fence(x) (gcc_unreachable (), NULL_RTX)
-#endif
-
-static void
-expand_builtin_mem_signal_fence (enum memmodel model)
-{
- if (HAVE_mem_signal_fence)
- emit_insn (gen_mem_signal_fence (GEN_INT (model)));
- else if (model != MEMMODEL_RELAXED)
- {
- rtx asm_op, clob;
-
- /* By default targets are coherent between a thread and the signal
- handler running on the same thread. Thus this really becomes a
- compiler barrier, in that stores must not be sunk past
- (or raised above) a given point. */
-
- /* Generate asm volatile("" : : : "memory") as the memory barrier. */
- asm_op = gen_rtx_ASM_OPERANDS (VOIDmode, empty_string, empty_string, 0,
- rtvec_alloc (0), rtvec_alloc (0),
- rtvec_alloc (0), UNKNOWN_LOCATION);
- MEM_VOLATILE_P (asm_op) = 1;
-
- clob = gen_rtx_SCRATCH (VOIDmode);
- clob = gen_rtx_MEM (BLKmode, clob);
- clob = gen_rtx_CLOBBER (VOIDmode, clob);
-
- emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, asm_op, clob)));
- }
+ enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
+ expand_mem_thread_fence (model);
}
/* Expand the __atomic_signal_fence intrinsic:
@@ -5745,10 +5688,8 @@ expand_builtin_mem_signal_fence (enum memmodel model)
static void
expand_builtin_atomic_signal_fence (tree exp)
{
- enum memmodel model;
-
- model = get_memmodel (CALL_EXPR_ARG (exp, 0));
- expand_builtin_mem_signal_fence (model);
+ enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
+ expand_mem_signal_fence (model);
}
/* Expand the __sync_synchronize intrinsic. */
@@ -5756,31 +5697,7 @@ expand_builtin_atomic_signal_fence (tree exp)
static void
expand_builtin_sync_synchronize (void)
{
- gimple x;
- VEC (tree, gc) *v_clobbers;
-
-#ifdef HAVE_memory_barrier
- if (HAVE_memory_barrier)
- {
- emit_insn (gen_memory_barrier ());
- return;
- }
-#endif
-
- if (synchronize_libfunc != NULL_RTX)
- {
- emit_library_call (synchronize_libfunc, LCT_NORMAL, VOIDmode, 0);
- return;
- }
-
- /* If no explicit memory barrier instruction is available, create an
- empty asm stmt with a memory clobber. */
- v_clobbers = VEC_alloc (tree, gc, 1);
- VEC_quick_push (tree, v_clobbers,
- tree_cons (NULL, build_string (6, "memory"), NULL));
- x = gimple_build_asm_vec ("", NULL, NULL, v_clobbers, NULL);
- gimple_asm_set_volatile (x, true);
- expand_asm_stmt (x);
+ expand_mem_thread_fence (MEMMODEL_SEQ_CST);
}
@@ -6578,12 +6495,28 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4:
case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8:
case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16:
- mode =
- get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1);
- target = expand_builtin_atomic_compare_exchange (mode, exp, target);
- if (target)
- return target;
- break;
+ {
+ unsigned int nargs, z;
+ VEC(tree,gc) *vec;
+
+ mode =
+ get_builtin_sync_mode (fcode - BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1);
+ target = expand_builtin_atomic_compare_exchange (mode, exp, target);
+ if (target)
+ return target;
+
+ /* If this is turned into an external library call, the weak parameter
+ must be dropped to match the expected parameter list. */
+ nargs = call_expr_nargs (exp);
+ vec = VEC_alloc (tree, gc, nargs - 1);
+ for (z = 0; z < 3; z++)
+ VEC_quick_push (tree, vec, CALL_EXPR_ARG (exp, z));
+ /* Skip the boolean weak parameter. */
+ for (z = 4; z < 6; z++)
+ VEC_quick_push (tree, vec, CALL_EXPR_ARG (exp, z));
+ exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), vec);
+ break;
+ }
case BUILT_IN_ATOMIC_LOAD_1:
case BUILT_IN_ATOMIC_LOAD_2:
@@ -6776,7 +6709,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break;
case BUILT_IN_ATOMIC_TEST_AND_SET:
- return expand_builtin_atomic_test_and_set (exp);
+ return expand_builtin_atomic_test_and_set (exp, target);
case BUILT_IN_ATOMIC_CLEAR:
return expand_builtin_atomic_clear (exp);
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 3cb29c0b3a2..44358a8c15e 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -2534,7 +2534,10 @@ warn_if_shadowing (tree new_decl)
/* Is anything being shadowed? Invisible decls do not count. */
for (b = I_SYMBOL_BINDING (DECL_NAME (new_decl)); b; b = b->shadowed)
- if (b->decl && b->decl != new_decl && !b->invisible)
+ if (b->decl && b->decl != new_decl && !b->invisible
+ && (b->decl == error_mark_node
+ || diagnostic_report_warnings_p (global_dc,
+ DECL_SOURCE_LOCATION (b->decl))))
{
tree old_decl = b->decl;
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 9716cc93f37..44631060789 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,13 @@
+2011-11-24 Andrew MacLeod <amacleod@redhat.com>
+
+ PR c/51256
+ * c-common.c (get_atomic_generic_size): Check for various error
+ conditions
+ (resolve_overloaded_atomic_exchange,
+ resolve_overloaded_atomic_compare_exchange,
+ resolve_overloaded_atomic_load, resolve_overloaded_atomic_store): Return
+ error_mark_node for error conditions.
+
2011-11-08 Richard Guenther <rguenther@suse.de>
PR middle-end/51010
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index a6823311321..fbbcb3841dd 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -9392,7 +9392,7 @@ get_atomic_generic_size (location_t loc, tree function, VEC(tree,gc) *params)
n_model = 2;
break;
default:
- return 0;
+ gcc_unreachable ();
}
if (VEC_length (tree, params) != n_param)
@@ -9403,13 +9403,33 @@ get_atomic_generic_size (location_t loc, tree function, VEC(tree,gc) *params)
/* Get type of first parameter, and determine its size. */
type_0 = TREE_TYPE (VEC_index (tree, params, 0));
- if (TREE_CODE (type_0) != POINTER_TYPE)
+ if (TREE_CODE (type_0) != POINTER_TYPE || VOID_TYPE_P (TREE_TYPE (type_0)))
+ {
+ error_at (loc, "argument 1 of %qE must be a non-void pointer type",
+ function);
+ return 0;
+ }
+
+ /* Types must be compile time constant sizes. */
+ if (TREE_CODE ((TYPE_SIZE_UNIT (TREE_TYPE (type_0)))) != INTEGER_CST)
{
- error_at (loc, "argument 1 of %qE must be a pointer type", function);
+ error_at (loc,
+ "argument 1 of %qE must be a pointer to a constant size type",
+ function);
return 0;
}
+
size_0 = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (type_0)), 1);
+ /* Zero size objects are not allowed. */
+ if (size_0 == 0)
+ {
+ error_at (loc,
+ "argument 1 of %qE must be a pointer to a nonzero size object",
+ function);
+ return 0;
+ }
+
/* Check each other parameter is a pointer and the same size. */
for (x = 0; x < n_param - n_model; x++)
{
@@ -9445,7 +9465,6 @@ get_atomic_generic_size (location_t loc, tree function, VEC(tree,gc) *params)
warning_at (loc, OPT_Winvalid_memory_model,
"invalid memory model argument %d of %qE", x + 1,
function);
- return MEMMODEL_SEQ_CST;
}
}
else
@@ -9515,6 +9534,13 @@ resolve_overloaded_atomic_exchange (location_t loc, tree function,
tree I_type, I_type_ptr;
int n = get_atomic_generic_size (loc, function, params);
+ /* Size of 0 is an error condition. */
+ if (n == 0)
+ {
+ *new_return = error_mark_node;
+ return true;
+ }
+
/* If not a lock-free size, change to the library generic format. */
if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
{
@@ -9538,8 +9564,7 @@ resolve_overloaded_atomic_exchange (location_t loc, tree function,
/* Convert object pointer to required type. */
p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
- VEC_replace (tree, params, 0, p0);
-
+ VEC_replace (tree, params, 0, p0);
/* Convert new value to required type, and dereference it. */
p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR);
p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1);
@@ -9574,6 +9599,13 @@ resolve_overloaded_atomic_compare_exchange (location_t loc, tree function,
tree I_type, I_type_ptr;
int n = get_atomic_generic_size (loc, function, params);
+ /* Size of 0 is an error condition. */
+ if (n == 0)
+ {
+ *new_return = error_mark_node;
+ return true;
+ }
+
/* If not a lock-free size, change to the library generic format. */
if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
{
@@ -9643,6 +9675,13 @@ resolve_overloaded_atomic_load (location_t loc, tree function,
tree I_type, I_type_ptr;
int n = get_atomic_generic_size (loc, function, params);
+ /* Size of 0 is an error condition. */
+ if (n == 0)
+ {
+ *new_return = error_mark_node;
+ return true;
+ }
+
/* If not a lock-free size, change to the library generic format. */
if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
{
@@ -9696,6 +9735,13 @@ resolve_overloaded_atomic_store (location_t loc, tree function,
tree I_type, I_type_ptr;
int n = get_atomic_generic_size (loc, function, params);
+ /* Size of 0 is an error condition. */
+ if (n == 0)
+ {
+ *new_return = error_mark_node;
+ return true;
+ }
+
/* If not a lock-free size, change to the library generic format. */
if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
{
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index 7622f0b155e..930423bcff6 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -494,7 +494,8 @@ add_to_renaming_pragma_list (tree oldname, tree newname)
p->newname = newname;
}
-static GTY(()) tree pragma_extern_prefix;
+/* The current prefix set by #pragma extern_prefix. */
+GTY(()) tree pragma_extern_prefix;
/* #pragma extern_prefix "prefix" */
static void
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index 04af94f3ddf..86681ae99cc 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -146,4 +146,6 @@ extern enum cpp_ttype c_lex_with_flags (tree *, location_t *, unsigned char *,
extern void c_pp_lookup_pragma (unsigned int, const char **, const char **);
+extern GTY(()) tree pragma_extern_prefix;
+
#endif /* GCC_C_PRAGMA_H */
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index aed390f31e8..b88b11fc430 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -10699,7 +10699,7 @@ c_parser_transaction_expression (c_parser *parser, enum rid keyword)
}
parser->in_transaction = this_in;
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
tree expr = c_parser_expression (parser).value;
ret.original_type = TREE_TYPE (expr);
@@ -10708,10 +10708,15 @@ c_parser_transaction_expression (c_parser *parser, enum rid keyword)
TRANSACTION_EXPR_RELAXED (ret.value) = 1;
SET_EXPR_LOCATION (ret.value, loc);
ret.original_code = TRANSACTION_EXPR;
+ if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ goto error;
+ }
}
else
{
- c_parser_error (parser, "expected %<(%>");
+ error:
ret.value = error_mark_node;
ret.original_code = ERROR_MARK;
ret.original_type = NULL;
diff --git a/gcc/calls.c b/gcc/calls.c
index 382de7fcdeb..316f1481ca0 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1668,6 +1668,8 @@ mem_overlaps_already_clobbered_arg_p (rtx addr, unsigned HOST_WIDE_INT size)
{
HOST_WIDE_INT i;
+ if (sbitmap_empty_p (stored_args_map))
+ return false;
if (addr == crtl->args.internal_arg_pointer)
i = 0;
else if (GET_CODE (addr) == PLUS
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 16e2eb30a6a..4b1d8350de5 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -1875,7 +1875,8 @@ rtl_verify_flow_info_1 (void)
| EDGE_CAN_FALLTHRU
| EDGE_IRREDUCIBLE_LOOP
| EDGE_LOOP_EXIT
- | EDGE_CROSSING)) == 0)
+ | EDGE_CROSSING
+ | EDGE_PRESERVE)) == 0)
n_branch++;
if (e->flags & EDGE_ABNORMAL_CALL)
@@ -2735,6 +2736,16 @@ cfg_layout_can_merge_blocks_p (basic_block a, basic_block b)
if (BB_PARTITION (a) != BB_PARTITION (b))
return false;
+ /* If we would end up moving B's instructions, make sure it doesn't fall
+ through into the exit block, since we cannot recover from a fallthrough
+ edge into the exit block occurring in the middle of a function. */
+ if (NEXT_INSN (BB_END (a)) != BB_HEAD (b))
+ {
+ edge e = find_fallthru_edge (b->succs);
+ if (e && e->dest == EXIT_BLOCK_PTR)
+ return false;
+ }
+
/* There must be exactly one edge in between the blocks. */
return (single_succ_p (a)
&& single_succ (a) == b
diff --git a/gcc/common.opt b/gcc/common.opt
index 4eb5b30b1c4..55d3f2d44d1 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1337,7 +1337,7 @@ EnumValue
Enum(ira_algorithm) String(priority) Value(IRA_ALGORITHM_PRIORITY)
fira-region=
-Common Joined RejectNegative Enum(ira_region) Var(flag_ira_region) Init(IRA_REGION_MIXED)
+Common Joined RejectNegative Enum(ira_region) Var(flag_ira_region) Init(IRA_REGION_AUTODETECT)
-fira-region=[one|all|mixed] Set regions for IRA
Enum
diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h
index 31551689a27..42b34d3a39c 100644
--- a/gcc/config/alpha/alpha-protos.h
+++ b/gcc/config/alpha/alpha-protos.h
@@ -88,15 +88,14 @@ extern bool alpha_emit_setcc (rtx[], enum machine_mode);
extern int alpha_split_conditional_move (enum rtx_code, rtx, rtx, rtx, rtx);
extern void alpha_emit_xfloating_arith (enum rtx_code, rtx[]);
extern void alpha_emit_xfloating_cvt (enum rtx_code, rtx[]);
-extern void alpha_split_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
-extern void alpha_split_compare_and_swap (rtx, rtx, rtx, rtx, rtx);
-extern void alpha_expand_compare_and_swap_12 (rtx, rtx, rtx, rtx);
-extern void alpha_split_compare_and_swap_12 (enum machine_mode, rtx, rtx,
- rtx, rtx, rtx, rtx, rtx);
-extern void alpha_split_lock_test_and_set (rtx, rtx, rtx, rtx);
-extern void alpha_expand_lock_test_and_set_12 (rtx, rtx, rtx);
-extern void alpha_split_lock_test_and_set_12 (enum machine_mode, rtx, rtx,
- rtx, rtx, rtx);
+extern void alpha_split_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx,
+ enum memmodel);
+extern void alpha_split_compare_and_swap (rtx op[]);
+extern void alpha_expand_compare_and_swap_12 (rtx op[]);
+extern void alpha_split_compare_and_swap_12 (rtx op[]);
+extern void alpha_split_atomic_exchange (rtx op[]);
+extern void alpha_expand_atomic_exchange_12 (rtx op[]);
+extern void alpha_split_atomic_exchange_12 (rtx op[]);
#endif
extern rtx alpha_use_linkage (rtx, bool, bool);
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 9a43f80243f..e970227dc4c 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -4196,6 +4196,47 @@ emit_store_conditional (enum machine_mode mode, rtx res, rtx mem, rtx val)
emit_insn (fn (res, mem, val));
}
+/* Subroutines of the atomic operation splitters. Emit barriers
+ as needed for the memory MODEL. */
+
+static void
+alpha_pre_atomic_barrier (enum memmodel model)
+{
+ switch (model)
+ {
+ case MEMMODEL_RELAXED:
+ case MEMMODEL_CONSUME:
+ case MEMMODEL_ACQUIRE:
+ break;
+ case MEMMODEL_RELEASE:
+ case MEMMODEL_ACQ_REL:
+ case MEMMODEL_SEQ_CST:
+ emit_insn (gen_memory_barrier ());
+ break;
+ default:
+ gcc_unreachable ();
+ }
+}
+
+static void
+alpha_post_atomic_barrier (enum memmodel model)
+{
+ switch (model)
+ {
+ case MEMMODEL_RELAXED:
+ case MEMMODEL_CONSUME:
+ case MEMMODEL_RELEASE:
+ break;
+ case MEMMODEL_ACQUIRE:
+ case MEMMODEL_ACQ_REL:
+ case MEMMODEL_SEQ_CST:
+ emit_insn (gen_memory_barrier ());
+ break;
+ default:
+ gcc_unreachable ();
+ }
+}
+
/* A subroutine of the atomic operation splitters. Emit an insxl
instruction in MODE. */
@@ -4236,13 +4277,13 @@ emit_insxl (enum machine_mode mode, rtx op1, rtx op2)
a scratch register. */
void
-alpha_split_atomic_op (enum rtx_code code, rtx mem, rtx val,
- rtx before, rtx after, rtx scratch)
+alpha_split_atomic_op (enum rtx_code code, rtx mem, rtx val, rtx before,
+ rtx after, rtx scratch, enum memmodel model)
{
enum machine_mode mode = GET_MODE (mem);
rtx label, x, cond = gen_rtx_REG (DImode, REGNO (scratch));
- emit_insn (gen_memory_barrier ());
+ alpha_pre_atomic_barrier (model);
label = gen_label_rtx ();
emit_label (label);
@@ -4270,29 +4311,48 @@ alpha_split_atomic_op (enum rtx_code code, rtx mem, rtx val,
x = gen_rtx_EQ (DImode, cond, const0_rtx);
emit_unlikely_jump (x, label);
- emit_insn (gen_memory_barrier ());
+ alpha_post_atomic_barrier (model);
}
/* Expand a compare and swap operation. */
void
-alpha_split_compare_and_swap (rtx retval, rtx mem, rtx oldval, rtx newval,
- rtx scratch)
+alpha_split_compare_and_swap (rtx operands[])
{
- enum machine_mode mode = GET_MODE (mem);
- rtx label1, label2, x, cond = gen_lowpart (DImode, scratch);
+ rtx cond, retval, mem, oldval, newval;
+ bool is_weak;
+ enum memmodel mod_s, mod_f;
+ enum machine_mode mode;
+ rtx label1, label2, x;
+
+ cond = operands[0];
+ retval = operands[1];
+ mem = operands[2];
+ oldval = operands[3];
+ newval = operands[4];
+ is_weak = (operands[5] != const0_rtx);
+ mod_s = (enum memmodel) INTVAL (operands[6]);
+ mod_f = (enum memmodel) INTVAL (operands[7]);
+ mode = GET_MODE (mem);
- emit_insn (gen_memory_barrier ());
+ alpha_pre_atomic_barrier (mod_s);
- label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
+ label1 = NULL_RTX;
+ if (!is_weak)
+ {
+ label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
+ emit_label (XEXP (label1, 0));
+ }
label2 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
- emit_label (XEXP (label1, 0));
emit_load_locked (mode, retval, mem);
x = gen_lowpart (DImode, retval);
if (oldval == const0_rtx)
- x = gen_rtx_NE (DImode, x, const0_rtx);
+ {
+ emit_move_insn (cond, const0_rtx);
+ x = gen_rtx_NE (DImode, x, const0_rtx);
+ }
else
{
x = gen_rtx_EQ (DImode, x, oldval);
@@ -4301,54 +4361,101 @@ alpha_split_compare_and_swap (rtx retval, rtx mem, rtx oldval, rtx newval,
}
emit_unlikely_jump (x, label2);
- emit_move_insn (scratch, newval);
- emit_store_conditional (mode, cond, mem, scratch);
+ emit_move_insn (cond, newval);
+ emit_store_conditional (mode, cond, mem, gen_lowpart (mode, cond));
- x = gen_rtx_EQ (DImode, cond, const0_rtx);
- emit_unlikely_jump (x, label1);
+ if (!is_weak)
+ {
+ x = gen_rtx_EQ (DImode, cond, const0_rtx);
+ emit_unlikely_jump (x, label1);
+ }
+
+ if (mod_f != MEMMODEL_RELAXED)
+ emit_label (XEXP (label2, 0));
- emit_insn (gen_memory_barrier ());
- emit_label (XEXP (label2, 0));
+ alpha_post_atomic_barrier (mod_s);
+
+ if (mod_f == MEMMODEL_RELAXED)
+ emit_label (XEXP (label2, 0));
}
void
-alpha_expand_compare_and_swap_12 (rtx dst, rtx mem, rtx oldval, rtx newval)
+alpha_expand_compare_and_swap_12 (rtx operands[])
{
- enum machine_mode mode = GET_MODE (mem);
+ rtx cond, dst, mem, oldval, newval, is_weak, mod_s, mod_f;
+ enum machine_mode mode;
rtx addr, align, wdst;
- rtx (*fn5) (rtx, rtx, rtx, rtx, rtx);
+ rtx (*gen) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+
+ cond = operands[0];
+ dst = operands[1];
+ mem = operands[2];
+ oldval = operands[3];
+ newval = operands[4];
+ is_weak = operands[5];
+ mod_s = operands[6];
+ mod_f = operands[7];
+ mode = GET_MODE (mem);
+
+ /* We forced the address into a register via mem_noofs_operand. */
+ addr = XEXP (mem, 0);
+ gcc_assert (register_operand (addr, DImode));
- addr = force_reg (DImode, XEXP (mem, 0));
align = expand_simple_binop (Pmode, AND, addr, GEN_INT (-8),
NULL_RTX, 1, OPTAB_DIRECT);
oldval = convert_modes (DImode, mode, oldval, 1);
- newval = emit_insxl (mode, newval, addr);
+
+ if (newval != const0_rtx)
+ newval = emit_insxl (mode, newval, addr);
wdst = gen_reg_rtx (DImode);
if (mode == QImode)
- fn5 = gen_sync_compare_and_swapqi_1;
+ gen = gen_atomic_compare_and_swapqi_1;
else
- fn5 = gen_sync_compare_and_swaphi_1;
- emit_insn (fn5 (wdst, addr, oldval, newval, align));
+ gen = gen_atomic_compare_and_swaphi_1;
+ emit_insn (gen (cond, wdst, mem, oldval, newval, align,
+ is_weak, mod_s, mod_f));
emit_move_insn (dst, gen_lowpart (mode, wdst));
}
void
-alpha_split_compare_and_swap_12 (enum machine_mode mode, rtx dest, rtx addr,
- rtx oldval, rtx newval, rtx align,
- rtx scratch, rtx cond)
+alpha_split_compare_and_swap_12 (rtx operands[])
{
- rtx label1, label2, mem, width, mask, x;
+ rtx cond, dest, orig_mem, oldval, newval, align, scratch;
+ enum machine_mode mode;
+ bool is_weak;
+ enum memmodel mod_s, mod_f;
+ rtx label1, label2, mem, addr, width, mask, x;
+
+ cond = operands[0];
+ dest = operands[1];
+ orig_mem = operands[2];
+ oldval = operands[3];
+ newval = operands[4];
+ align = operands[5];
+ is_weak = (operands[6] != const0_rtx);
+ mod_s = (enum memmodel) INTVAL (operands[7]);
+ mod_f = (enum memmodel) INTVAL (operands[8]);
+ scratch = operands[9];
+ mode = GET_MODE (orig_mem);
+ addr = XEXP (orig_mem, 0);
mem = gen_rtx_MEM (DImode, align);
- MEM_VOLATILE_P (mem) = 1;
+ MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (orig_mem);
+ if (MEM_ALIAS_SET (orig_mem) == ALIAS_SET_MEMORY_BARRIER)
+ set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
+
+ alpha_pre_atomic_barrier (mod_s);
- emit_insn (gen_memory_barrier ());
- label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
+ label1 = NULL_RTX;
+ if (!is_weak)
+ {
+ label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
+ emit_label (XEXP (label1, 0));
+ }
label2 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
- emit_label (XEXP (label1, 0));
emit_load_locked (DImode, scratch, mem);
@@ -4357,7 +4464,10 @@ alpha_split_compare_and_swap_12 (enum machine_mode mode, rtx dest, rtx addr,
emit_insn (gen_extxl (dest, scratch, width, addr));
if (oldval == const0_rtx)
- x = gen_rtx_NE (DImode, dest, const0_rtx);
+ {
+ emit_move_insn (cond, const0_rtx);
+ x = gen_rtx_NE (DImode, dest, const0_rtx);
+ }
else
{
x = gen_rtx_EQ (DImode, dest, oldval);
@@ -4366,25 +4476,47 @@ alpha_split_compare_and_swap_12 (enum machine_mode mode, rtx dest, rtx addr,
}
emit_unlikely_jump (x, label2);
- emit_insn (gen_mskxl (scratch, scratch, mask, addr));
- emit_insn (gen_iordi3 (scratch, scratch, newval));
+ emit_insn (gen_mskxl (cond, scratch, mask, addr));
- emit_store_conditional (DImode, scratch, mem, scratch);
+ if (newval != const0_rtx)
+ emit_insn (gen_iordi3 (cond, cond, newval));
- x = gen_rtx_EQ (DImode, scratch, const0_rtx);
- emit_unlikely_jump (x, label1);
+ emit_store_conditional (DImode, cond, mem, cond);
- emit_insn (gen_memory_barrier ());
- emit_label (XEXP (label2, 0));
+ if (!is_weak)
+ {
+ x = gen_rtx_EQ (DImode, cond, const0_rtx);
+ emit_unlikely_jump (x, label1);
+ }
+
+ if (mod_f != MEMMODEL_RELAXED)
+ emit_label (XEXP (label2, 0));
+
+ alpha_post_atomic_barrier (mod_s);
+
+ if (mod_f == MEMMODEL_RELAXED)
+ emit_label (XEXP (label2, 0));
}
/* Expand an atomic exchange operation. */
void
-alpha_split_lock_test_and_set (rtx retval, rtx mem, rtx val, rtx scratch)
+alpha_split_atomic_exchange (rtx operands[])
{
- enum machine_mode mode = GET_MODE (mem);
- rtx label, x, cond = gen_lowpart (DImode, scratch);
+ rtx retval, mem, val, scratch;
+ enum memmodel model;
+ enum machine_mode mode;
+ rtx label, x, cond;
+
+ retval = operands[0];
+ mem = operands[1];
+ val = operands[2];
+ model = (enum memmodel) INTVAL (operands[3]);
+ scratch = operands[4];
+ mode = GET_MODE (mem);
+ cond = gen_lowpart (DImode, scratch);
+
+ alpha_pre_atomic_barrier (model);
label = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
emit_label (XEXP (label, 0));
@@ -4396,44 +4528,67 @@ alpha_split_lock_test_and_set (rtx retval, rtx mem, rtx val, rtx scratch)
x = gen_rtx_EQ (DImode, cond, const0_rtx);
emit_unlikely_jump (x, label);
- emit_insn (gen_memory_barrier ());
+ alpha_post_atomic_barrier (model);
}
void
-alpha_expand_lock_test_and_set_12 (rtx dst, rtx mem, rtx val)
+alpha_expand_atomic_exchange_12 (rtx operands[])
{
- enum machine_mode mode = GET_MODE (mem);
+ rtx dst, mem, val, model;
+ enum machine_mode mode;
rtx addr, align, wdst;
- rtx (*fn4) (rtx, rtx, rtx, rtx);
+ rtx (*gen) (rtx, rtx, rtx, rtx, rtx);
+
+ dst = operands[0];
+ mem = operands[1];
+ val = operands[2];
+ model = operands[3];
+ mode = GET_MODE (mem);
- /* Force the address into a register. */
- addr = force_reg (DImode, XEXP (mem, 0));
+ /* We forced the address into a register via mem_noofs_operand. */
+ addr = XEXP (mem, 0);
+ gcc_assert (register_operand (addr, DImode));
- /* Align it to a multiple of 8. */
align = expand_simple_binop (Pmode, AND, addr, GEN_INT (-8),
NULL_RTX, 1, OPTAB_DIRECT);
/* Insert val into the correct byte location within the word. */
- val = emit_insxl (mode, val, addr);
+ if (val != const0_rtx)
+ val = emit_insxl (mode, val, addr);
wdst = gen_reg_rtx (DImode);
if (mode == QImode)
- fn4 = gen_sync_lock_test_and_setqi_1;
+ gen = gen_atomic_exchangeqi_1;
else
- fn4 = gen_sync_lock_test_and_sethi_1;
- emit_insn (fn4 (wdst, addr, val, align));
+ gen = gen_atomic_exchangehi_1;
+ emit_insn (gen (wdst, mem, val, align, model));
emit_move_insn (dst, gen_lowpart (mode, wdst));
}
void
-alpha_split_lock_test_and_set_12 (enum machine_mode mode, rtx dest, rtx addr,
- rtx val, rtx align, rtx scratch)
+alpha_split_atomic_exchange_12 (rtx operands[])
{
+ rtx dest, orig_mem, addr, val, align, scratch;
rtx label, mem, width, mask, x;
+ enum machine_mode mode;
+ enum memmodel model;
+
+ dest = operands[0];
+ orig_mem = operands[1];
+ val = operands[2];
+ align = operands[3];
+ model = (enum memmodel) INTVAL (operands[4]);
+ scratch = operands[5];
+ mode = GET_MODE (orig_mem);
+ addr = XEXP (orig_mem, 0);
mem = gen_rtx_MEM (DImode, align);
- MEM_VOLATILE_P (mem) = 1;
+ MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (orig_mem);
+ if (MEM_ALIAS_SET (orig_mem) == ALIAS_SET_MEMORY_BARRIER)
+ set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
+
+ alpha_pre_atomic_barrier (model);
label = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
emit_label (XEXP (label, 0));
@@ -4444,14 +4599,15 @@ alpha_split_lock_test_and_set_12 (enum machine_mode mode, rtx dest, rtx addr,
mask = GEN_INT (mode == QImode ? 0xff : 0xffff);
emit_insn (gen_extxl (dest, scratch, width, addr));
emit_insn (gen_mskxl (scratch, scratch, mask, addr));
- emit_insn (gen_iordi3 (scratch, scratch, val));
+ if (val != const0_rtx)
+ emit_insn (gen_iordi3 (scratch, scratch, val));
emit_store_conditional (DImode, scratch, mem, scratch);
x = gen_rtx_EQ (DImode, scratch, const0_rtx);
emit_unlikely_jump (x, label);
- emit_insn (gen_memory_barrier ());
+ alpha_post_atomic_barrier (model);
}
/* Adjust the cost of a scheduling dependency. Return the new cost of
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index 64229245065..e715cc86422 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -81,6 +81,7 @@
UNSPECV_SETJMPR_ER ; builtin_setjmp_receiver fragment
UNSPECV_LL ; load-locked
UNSPECV_SC ; store-conditional
+ UNSPECV_CMPXCHG
])
;; On non-BWX targets, CQImode must be handled the similarly to HImode
diff --git a/gcc/config/alpha/constraints.md b/gcc/config/alpha/constraints.md
index 35514502c20..62c7f9ae0c5 100644
--- a/gcc/config/alpha/constraints.md
+++ b/gcc/config/alpha/constraints.md
@@ -19,7 +19,7 @@
;;; Unused letters:
;;; ABCDEF V YZ
-;;; de ghijklmnopq stu wxyz
+;;; de ghijkl pq tu wxyz
;; Integer register constraints.
@@ -38,6 +38,10 @@
(define_register_constraint "v" "R0_REG"
"General register 0, function value return address")
+(define_memory_constraint "w"
+ "A memory whose address is only a register"
+ (match_operand 0 "mem_noofs_operand"))
+
;; Integer constant constraints.
(define_constraint "I"
"An unsigned 8 bit constant"
diff --git a/gcc/config/alpha/predicates.md b/gcc/config/alpha/predicates.md
index c1e3115aead..598742f81e7 100644
--- a/gcc/config/alpha/predicates.md
+++ b/gcc/config/alpha/predicates.md
@@ -623,3 +623,8 @@
(ior (match_operand 0 "register_operand")
(and (match_test "TARGET_BWX")
(match_operand 0 "memory_operand"))))
+
+;; Accept a memory whose address is only a register.
+(define_predicate "mem_noofs_operand"
+ (and (match_code "mem")
+ (match_code "reg" "0")))
diff --git a/gcc/config/alpha/sync.md b/gcc/config/alpha/sync.md
index bb7210239fd..90f6c5cd8d4 100644
--- a/gcc/config/alpha/sync.md
+++ b/gcc/config/alpha/sync.md
@@ -1,5 +1,5 @@
;; GCC machine description for Alpha synchronization instructions.
-;; Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -62,95 +62,160 @@
[(set_attr "type" "st_c")])
;; The Alpha Architecture Handbook says that it is UNPREDICTABLE whether
-;; the lock is cleared by a TAKEN branch. This means that we can not
-;; expand a ll/sc sequence until after the final basic-block reordering pass.
+;; the lock is cleared by a normal load or store. This means we cannot
+;; expand a ll/sc sequence before reload, lest a register spill is
+;; inserted inside the sequence. It is also UNPREDICTABLE whether the
+;; lock is cleared by a TAKEN branch. This means that we can not expand
+;; a ll/sc sequence containing a branch (i.e. compare-and-swap) until after
+;; the final basic-block reordering pass.
-(define_insn_and_split "sync_<fetchop_name><mode>"
- [(set (match_operand:I48MODE 0 "memory_operand" "+m")
- (unspec:I48MODE
- [(FETCHOP:I48MODE (match_dup 0)
- (match_operand:I48MODE 1 "<fetchop_pred>" "<fetchop_constr>"))]
- UNSPEC_ATOMIC))
- (clobber (match_scratch:I48MODE 2 "=&r"))]
+(define_expand "atomic_compare_and_swap<mode>"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "") ;; bool out
+ (unspec_volatile:DI [(const_int 0)] UNSPECV_CMPXCHG))
+ (set (match_operand:I48MODE 1 "register_operand" "") ;; val out
+ (unspec_volatile:I48MODE [(const_int 0)] UNSPECV_CMPXCHG))
+ (set (match_operand:I48MODE 2 "memory_operand" "") ;; memory
+ (unspec_volatile:I48MODE
+ [(match_dup 2)
+ (match_operand:I48MODE 3 "reg_or_8bit_operand" "") ;; expected
+ (match_operand:I48MODE 4 "add_operand" "") ;; desired
+ (match_operand:SI 5 "const_int_operand" "") ;; is_weak
+ (match_operand:SI 6 "const_int_operand" "") ;; succ model
+ (match_operand:SI 7 "const_int_operand" "")] ;; fail model
+ UNSPECV_CMPXCHG))])]
+ ""
+{
+ if (<MODE>mode == SImode)
+ {
+ operands[3] = convert_modes (DImode, SImode, operands[3], 0);
+ operands[4] = convert_modes (DImode, SImode, operands[4], 0);
+ }
+})
+
+(define_insn_and_split "*atomic_compare_and_swap<mode>"
+ [(set (match_operand:DI 0 "register_operand" "=&r") ;; bool out
+ (unspec_volatile:DI [(const_int 0)] UNSPECV_CMPXCHG))
+ (set (match_operand:I48MODE 1 "register_operand" "=&r") ;; val out
+ (unspec_volatile:I48MODE [(const_int 0)] UNSPECV_CMPXCHG))
+ (set (match_operand:I48MODE 2 "memory_operand" "+m") ;; memory
+ (unspec_volatile:I48MODE
+ [(match_dup 2)
+ (match_operand:DI 3 "reg_or_8bit_operand" "rI") ;; expected
+ (match_operand:DI 4 "add_operand" "rKL") ;; desired
+ (match_operand:SI 5 "const_int_operand" "") ;; is_weak
+ (match_operand:SI 6 "const_int_operand" "") ;; succ model
+ (match_operand:SI 7 "const_int_operand" "")] ;; fail model
+ UNSPECV_CMPXCHG))]
""
"#"
"epilogue_completed"
[(const_int 0)]
{
- alpha_split_atomic_op (<CODE>, operands[0], operands[1],
- NULL, NULL, operands[2]);
+ alpha_split_compare_and_swap (operands);
DONE;
}
[(set_attr "type" "multi")])
-(define_insn_and_split "sync_nand<mode>"
- [(set (match_operand:I48MODE 0 "memory_operand" "+m")
- (unspec:I48MODE
- [(not:I48MODE
- (and:I48MODE (match_dup 0)
- (match_operand:I48MODE 1 "register_operand" "r")))]
- UNSPEC_ATOMIC))
- (clobber (match_scratch:I48MODE 2 "=&r"))]
+(define_expand "atomic_compare_and_swap<mode>"
+ [(match_operand:DI 0 "register_operand" "") ;; bool out
+ (match_operand:I12MODE 1 "register_operand" "") ;; val out
+ (match_operand:I12MODE 2 "mem_noofs_operand" "") ;; memory
+ (match_operand:I12MODE 3 "register_operand" "") ;; expected
+ (match_operand:I12MODE 4 "add_operand" "") ;; desired
+ (match_operand:SI 5 "const_int_operand" "") ;; is_weak
+ (match_operand:SI 6 "const_int_operand" "") ;; succ model
+ (match_operand:SI 7 "const_int_operand" "")] ;; fail model
+ ""
+{
+ alpha_expand_compare_and_swap_12 (operands);
+ DONE;
+})
+
+(define_insn_and_split "atomic_compare_and_swap<mode>_1"
+ [(set (match_operand:DI 0 "register_operand" "=&r") ;; bool out
+ (unspec_volatile:DI [(const_int 0)] UNSPECV_CMPXCHG))
+ (set (match_operand:DI 1 "register_operand" "=&r") ;; val out
+ (zero_extend:DI
+ (unspec_volatile:I12MODE [(const_int 0)] UNSPECV_CMPXCHG)))
+ (set (match_operand:I12MODE 2 "mem_noofs_operand" "+w") ;; memory
+ (unspec_volatile:I12MODE
+ [(match_dup 2)
+ (match_operand:DI 3 "reg_or_8bit_operand" "rI") ;; expected
+ (match_operand:DI 4 "reg_or_0_operand" "rJ") ;; desired
+ (match_operand:DI 5 "register_operand" "r") ;; align
+ (match_operand:SI 6 "const_int_operand" "") ;; is_weak
+ (match_operand:SI 7 "const_int_operand" "") ;; succ model
+ (match_operand:SI 8 "const_int_operand" "")] ;; fail model
+ UNSPECV_CMPXCHG))
+ (clobber (match_scratch:DI 9 "=&r"))]
""
"#"
"epilogue_completed"
[(const_int 0)]
{
- alpha_split_atomic_op (NOT, operands[0], operands[1],
- NULL, NULL, operands[2]);
+ alpha_split_compare_and_swap_12 (operands);
DONE;
}
[(set_attr "type" "multi")])
-(define_insn_and_split "sync_old_<fetchop_name><mode>"
- [(set (match_operand:I48MODE 0 "register_operand" "=&r")
- (match_operand:I48MODE 1 "memory_operand" "+m"))
+(define_insn_and_split "atomic_exchange<mode>"
+ [(set (match_operand:I48MODE 0 "register_operand" "=&r") ;; output
+ (match_operand:I48MODE 1 "memory_operand" "+m")) ;; memory
(set (match_dup 1)
(unspec:I48MODE
- [(FETCHOP:I48MODE (match_dup 1)
- (match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>"))]
- UNSPEC_ATOMIC))
- (clobber (match_scratch:I48MODE 3 "=&r"))]
+ [(match_operand:I48MODE 2 "add_operand" "rKL") ;; input
+ (match_operand:SI 3 "const_int_operand" "")] ;; model
+ UNSPEC_XCHG))
+ (clobber (match_scratch:I48MODE 4 "=&r"))]
""
"#"
"epilogue_completed"
[(const_int 0)]
{
- alpha_split_atomic_op (<CODE>, operands[1], operands[2],
- operands[0], NULL, operands[3]);
+ alpha_split_atomic_exchange (operands);
DONE;
}
[(set_attr "type" "multi")])
-(define_insn_and_split "sync_old_nand<mode>"
- [(set (match_operand:I48MODE 0 "register_operand" "=&r")
- (match_operand:I48MODE 1 "memory_operand" "+m"))
+(define_expand "atomic_exchange<mode>"
+ [(match_operand:I12MODE 0 "register_operand" "") ;; output
+ (match_operand:I12MODE 1 "mem_noofs_operand" "") ;; memory
+ (match_operand:I12MODE 2 "reg_or_0_operand" "") ;; input
+ (match_operand:SI 3 "const_int_operand" "")] ;; model
+ ""
+{
+ alpha_expand_atomic_exchange_12 (operands);
+ DONE;
+})
+
+(define_insn_and_split "atomic_exchange<mode>_1"
+ [(set (match_operand:DI 0 "register_operand" "=&r") ;; output
+ (zero_extend:DI
+ (match_operand:I12MODE 1 "mem_noofs_operand" "+w"))) ;; memory
(set (match_dup 1)
- (unspec:I48MODE
- [(not:I48MODE
- (and:I48MODE (match_dup 1)
- (match_operand:I48MODE 2 "register_operand" "r")))]
- UNSPEC_ATOMIC))
- (clobber (match_scratch:I48MODE 3 "=&r"))]
+ (unspec:I12MODE
+ [(match_operand:DI 2 "reg_or_8bit_operand" "rI") ;; input
+ (match_operand:DI 3 "register_operand" "r") ;; align
+ (match_operand:SI 4 "const_int_operand" "")] ;; model
+ UNSPEC_XCHG))
+ (clobber (match_scratch:DI 5 "=&r"))]
""
"#"
"epilogue_completed"
[(const_int 0)]
{
- alpha_split_atomic_op (NOT, operands[1], operands[2],
- operands[0], NULL, operands[3]);
+ alpha_split_atomic_exchange_12 (operands);
DONE;
}
[(set_attr "type" "multi")])
-(define_insn_and_split "sync_new_<fetchop_name><mode>"
- [(set (match_operand:I48MODE 0 "register_operand" "=&r")
- (FETCHOP:I48MODE
- (match_operand:I48MODE 1 "memory_operand" "+m")
- (match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>")))
- (set (match_dup 1)
+(define_insn_and_split "atomic_<fetchop_name><mode>"
+ [(set (match_operand:I48MODE 0 "memory_operand" "+m")
(unspec:I48MODE
- [(FETCHOP:I48MODE (match_dup 1) (match_dup 2))]
+ [(FETCHOP:I48MODE (match_dup 0)
+ (match_operand:I48MODE 1 "<fetchop_pred>" "<fetchop_constr>"))
+ (match_operand:SI 2 "const_int_operand" "")]
UNSPEC_ATOMIC))
(clobber (match_scratch:I48MODE 3 "=&r"))]
""
@@ -158,20 +223,20 @@
"epilogue_completed"
[(const_int 0)]
{
- alpha_split_atomic_op (<CODE>, operands[1], operands[2],
- NULL, operands[0], operands[3]);
+ alpha_split_atomic_op (<CODE>, operands[0], operands[1],
+ NULL, NULL, operands[3],
+ (enum memmodel) INTVAL (operands[2]));
DONE;
}
[(set_attr "type" "multi")])
-(define_insn_and_split "sync_new_nand<mode>"
- [(set (match_operand:I48MODE 0 "register_operand" "=&r")
- (not:I48MODE
- (and:I48MODE (match_operand:I48MODE 1 "memory_operand" "+m")
- (match_operand:I48MODE 2 "register_operand" "r"))))
- (set (match_dup 1)
+(define_insn_and_split "atomic_nand<mode>"
+ [(set (match_operand:I48MODE 0 "memory_operand" "+m")
(unspec:I48MODE
- [(not:I48MODE (and:I48MODE (match_dup 1) (match_dup 2)))]
+ [(not:I48MODE
+ (and:I48MODE (match_dup 0)
+ (match_operand:I48MODE 1 "register_operand" "r")))
+ (match_operand:SI 2 "const_int_operand" "")]
UNSPEC_ATOMIC))
(clobber (match_scratch:I48MODE 3 "=&r"))]
""
@@ -179,130 +244,100 @@
"epilogue_completed"
[(const_int 0)]
{
- alpha_split_atomic_op (NOT, operands[1], operands[2],
- NULL, operands[0], operands[3]);
+ alpha_split_atomic_op (NOT, operands[0], operands[1],
+ NULL, NULL, operands[3],
+ (enum memmodel) INTVAL (operands[2]));
DONE;
}
[(set_attr "type" "multi")])
-(define_expand "sync_compare_and_swap<mode>"
- [(match_operand:I12MODE 0 "register_operand" "")
- (match_operand:I12MODE 1 "memory_operand" "")
- (match_operand:I12MODE 2 "register_operand" "")
- (match_operand:I12MODE 3 "add_operand" "")]
- ""
-{
- alpha_expand_compare_and_swap_12 (operands[0], operands[1],
- operands[2], operands[3]);
- DONE;
-})
-
-(define_insn_and_split "sync_compare_and_swap<mode>_1"
- [(set (match_operand:DI 0 "register_operand" "=&r,&r")
- (zero_extend:DI
- (mem:I12MODE (match_operand:DI 1 "register_operand" "r,r"))))
- (set (mem:I12MODE (match_dup 1))
- (unspec:I12MODE
- [(match_operand:DI 2 "reg_or_8bit_operand" "J,rI")
- (match_operand:DI 3 "register_operand" "r,r")
- (match_operand:DI 4 "register_operand" "r,r")]
- UNSPEC_CMPXCHG))
- (clobber (match_scratch:DI 5 "=&r,&r"))
- (clobber (match_scratch:DI 6 "=X,&r"))]
+(define_insn_and_split "atomic_fetch_<fetchop_name><mode>"
+ [(set (match_operand:I48MODE 0 "register_operand" "=&r")
+ (match_operand:I48MODE 1 "memory_operand" "+m"))
+ (set (match_dup 1)
+ (unspec:I48MODE
+ [(FETCHOP:I48MODE (match_dup 1)
+ (match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>"))
+ (match_operand:SI 3 "const_int_operand" "")]
+ UNSPEC_ATOMIC))
+ (clobber (match_scratch:I48MODE 4 "=&r"))]
""
"#"
"epilogue_completed"
[(const_int 0)]
{
- alpha_split_compare_and_swap_12 (<MODE>mode, operands[0], operands[1],
- operands[2], operands[3], operands[4],
- operands[5], operands[6]);
+ alpha_split_atomic_op (<CODE>, operands[1], operands[2],
+ operands[0], NULL, operands[4],
+ (enum memmodel) INTVAL (operands[3]));
DONE;
}
[(set_attr "type" "multi")])
-(define_expand "sync_compare_and_swap<mode>"
- [(parallel
- [(set (match_operand:I48MODE 0 "register_operand" "")
- (match_operand:I48MODE 1 "memory_operand" ""))
- (set (match_dup 1)
- (unspec:I48MODE
- [(match_operand:I48MODE 2 "reg_or_8bit_operand" "")
- (match_operand:I48MODE 3 "add_operand" "rKL")]
- UNSPEC_CMPXCHG))
- (clobber (match_scratch:I48MODE 4 "=&r"))])]
- ""
-{
- if (<MODE>mode == SImode)
- operands[2] = convert_modes (DImode, SImode, operands[2], 0);
-})
-
-(define_insn_and_split "*sync_compare_and_swap<mode>"
+(define_insn_and_split "atomic_fetch_nand<mode>"
[(set (match_operand:I48MODE 0 "register_operand" "=&r")
(match_operand:I48MODE 1 "memory_operand" "+m"))
(set (match_dup 1)
(unspec:I48MODE
- [(match_operand:DI 2 "reg_or_8bit_operand" "rI")
- (match_operand:I48MODE 3 "add_operand" "rKL")]
- UNSPEC_CMPXCHG))
+ [(not:I48MODE
+ (and:I48MODE (match_dup 1)
+ (match_operand:I48MODE 2 "register_operand" "r")))
+ (match_operand:SI 3 "const_int_operand" "")]
+ UNSPEC_ATOMIC))
(clobber (match_scratch:I48MODE 4 "=&r"))]
""
"#"
"epilogue_completed"
[(const_int 0)]
{
- alpha_split_compare_and_swap (operands[0], operands[1], operands[2],
- operands[3], operands[4]);
+ alpha_split_atomic_op (NOT, operands[1], operands[2],
+ operands[0], NULL, operands[4],
+ (enum memmodel) INTVAL (operands[3]));
DONE;
}
[(set_attr "type" "multi")])
-(define_expand "sync_lock_test_and_set<mode>"
- [(match_operand:I12MODE 0 "register_operand" "")
- (match_operand:I12MODE 1 "memory_operand" "")
- (match_operand:I12MODE 2 "register_operand" "")]
- ""
-{
- alpha_expand_lock_test_and_set_12 (operands[0], operands[1], operands[2]);
- DONE;
-})
-
-(define_insn_and_split "sync_lock_test_and_set<mode>_1"
- [(set (match_operand:DI 0 "register_operand" "=&r")
- (zero_extend:DI
- (mem:I12MODE (match_operand:DI 1 "register_operand" "r"))))
- (set (mem:I12MODE (match_dup 1))
- (unspec:I12MODE
- [(match_operand:DI 2 "reg_or_8bit_operand" "rI")
- (match_operand:DI 3 "register_operand" "r")]
- UNSPEC_XCHG))
- (clobber (match_scratch:DI 4 "=&r"))]
+(define_insn_and_split "atomic_<fetchop_name>_fetch<mode>"
+ [(set (match_operand:I48MODE 0 "register_operand" "=&r")
+ (FETCHOP:I48MODE
+ (match_operand:I48MODE 1 "memory_operand" "+m")
+ (match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>")))
+ (set (match_dup 1)
+ (unspec:I48MODE
+ [(FETCHOP:I48MODE (match_dup 1) (match_dup 2))
+ (match_operand:SI 3 "const_int_operand" "")]
+ UNSPEC_ATOMIC))
+ (clobber (match_scratch:I48MODE 4 "=&r"))]
""
"#"
"epilogue_completed"
[(const_int 0)]
{
- alpha_split_lock_test_and_set_12 (<MODE>mode, operands[0], operands[1],
- operands[2], operands[3], operands[4]);
+ alpha_split_atomic_op (<CODE>, operands[1], operands[2],
+ NULL, operands[0], operands[4],
+ (enum memmodel) INTVAL (operands[3]));
DONE;
}
[(set_attr "type" "multi")])
-(define_insn_and_split "sync_lock_test_and_set<mode>"
+(define_insn_and_split "atomic_nand_fetch<mode>"
[(set (match_operand:I48MODE 0 "register_operand" "=&r")
- (match_operand:I48MODE 1 "memory_operand" "+m"))
+ (not:I48MODE
+ (and:I48MODE (match_operand:I48MODE 1 "memory_operand" "+m")
+ (match_operand:I48MODE 2 "register_operand" "r"))))
(set (match_dup 1)
(unspec:I48MODE
- [(match_operand:I48MODE 2 "add_operand" "rKL")]
- UNSPEC_XCHG))
- (clobber (match_scratch:I48MODE 3 "=&r"))]
+ [(not:I48MODE (and:I48MODE (match_dup 1) (match_dup 2)))
+ (match_operand:SI 3 "const_int_operand" "")]
+ UNSPEC_ATOMIC))
+ (clobber (match_scratch:I48MODE 4 "=&r"))]
""
"#"
"epilogue_completed"
[(const_int 0)]
{
- alpha_split_lock_test_and_set (operands[0], operands[1],
- operands[2], operands[3]);
+ alpha_split_atomic_op (NOT, operands[1], operands[2],
+ NULL, operands[0], operands[4],
+ (enum memmodel) INTVAL (operands[3]));
DONE;
}
[(set_attr "type" "multi")])
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 6ef6f62d28d..ee26c51b0a0 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -1096,6 +1096,10 @@ arm_set_fixed_conv_libfunc (convert_optab optable, enum machine_mode to,
static void
arm_init_libfuncs (void)
{
+ /* For Linux, we have access to kernel support for atomic operations. */
+ if (arm_abi == ARM_ABI_AAPCS_LINUX)
+ init_sync_libfuncs (2 * UNITS_PER_WORD);
+
/* There are no special library functions unless we are using the
ARM BPABI. */
if (!TARGET_BPABI)
@@ -10247,6 +10251,9 @@ store_multiple_sequence (rtx *operands, int nops, int nops_total,
rtx base_reg_rtx = NULL;
int i, stm_case;
+ /* Write back of base register is currently only supported for Thumb 1. */
+ int base_writeback = TARGET_THUMB1;
+
/* Can only handle up to MAX_LDM_STM_OPS insns at present, though could be
easily extended if required. */
gcc_assert (nops >= 2 && nops <= MAX_LDM_STM_OPS);
@@ -10304,7 +10311,9 @@ store_multiple_sequence (rtx *operands, int nops, int nops_total,
/* If it isn't an integer register, then we can't do this. */
if (unsorted_regs[i] < 0
|| (TARGET_THUMB1 && unsorted_regs[i] > LAST_LO_REGNUM)
- || (TARGET_THUMB2 && unsorted_regs[i] == base_reg)
+ /* The effects are unpredictable if the base register is
+ both updated and stored. */
+ || (base_writeback && unsorted_regs[i] == base_reg)
|| (TARGET_THUMB2 && unsorted_regs[i] == SP_REGNUM)
|| unsorted_regs[i] > 14)
return 0;
@@ -20723,39 +20732,34 @@ neon_emit_pair_result_insn (enum machine_mode mode,
emit_move_insn (mem, tmp2);
}
-/* Set up operands for a register copy from src to dest, taking care not to
- clobber registers in the process.
- FIXME: This has rather high polynomial complexity (O(n^3)?) but shouldn't
- be called with a large N, so that should be OK. */
+/* Set up OPERANDS for a register copy from SRC to DEST, taking care
+ not to early-clobber SRC registers in the process.
+ We assume that the operands described by SRC and DEST represent a
+ decomposed copy of OPERANDS[1] into OPERANDS[0]. COUNT is the
+ number of components into which the copy has been decomposed. */
void
neon_disambiguate_copy (rtx *operands, rtx *dest, rtx *src, unsigned int count)
{
- unsigned int copied = 0, opctr = 0;
- unsigned int done = (1 << count) - 1;
- unsigned int i, j;
+ unsigned int i;
- while (copied != done)
+ if (!reg_overlap_mentioned_p (operands[0], operands[1])
+ || REGNO (operands[0]) < REGNO (operands[1]))
{
for (i = 0; i < count; i++)
- {
- int good = 1;
-
- for (j = 0; good && j < count; j++)
- if (i != j && (copied & (1 << j)) == 0
- && reg_overlap_mentioned_p (src[j], dest[i]))
- good = 0;
-
- if (good)
- {
- operands[opctr++] = dest[i];
- operands[opctr++] = src[i];
- copied |= 1 << i;
- }
- }
+ {
+ operands[2 * i] = dest[i];
+ operands[2 * i + 1] = src[i];
+ }
+ }
+ else
+ {
+ for (i = 0; i < count; i++)
+ {
+ operands[2 * i] = dest[count - i - 1];
+ operands[2 * i + 1] = src[count - i - 1];
+ }
}
-
- gcc_assert (opctr == count * 2);
}
/* Expand an expression EXP that calls a built-in function,
diff --git a/gcc/config/avr/avr-c.c b/gcc/config/avr/avr-c.c
index 55de2d7fe4b..fd03b361b5e 100644
--- a/gcc/config/avr/avr-c.c
+++ b/gcc/config/avr/avr-c.c
@@ -18,6 +18,7 @@
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+/* Not included in avr.c since this requires C front end. */
#include "config.h"
#include "system.h"
@@ -27,8 +28,23 @@
#include "cpplib.h"
#include "tree.h"
#include "c-family/c-common.h"
+#include "langhooks.h"
+
+
+/* Implement `REGISTER_TARGET_PRAGMAS'. */
+
+void
+avr_register_target_pragmas (void)
+{
+ c_register_addr_space ("__pgm", ADDR_SPACE_PGM);
+ c_register_addr_space ("__pgm1", ADDR_SPACE_PGM1);
+ c_register_addr_space ("__pgm2", ADDR_SPACE_PGM2);
+ c_register_addr_space ("__pgm3", ADDR_SPACE_PGM3);
+ c_register_addr_space ("__pgm4", ADDR_SPACE_PGM4);
+ c_register_addr_space ("__pgm5", ADDR_SPACE_PGM5);
+ c_register_addr_space ("__pgmx", ADDR_SPACE_PGMX);
+}
-/* Not included in avr.c since this requires C front end. */
/* Worker function for TARGET_CPU_CPP_BUILTINS. */
@@ -90,6 +106,26 @@ avr_cpu_cpp_builtins (struct cpp_reader *pfile)
cpp_define (pfile, "__AVR_ERRATA_SKIP_JMP_CALL__");
}
+ cpp_define_formatted (pfile, "__AVR_SFR_OFFSET__=0x%x",
+ avr_current_arch->sfr_offset);
+
+ /* Define builtin macros so that the user can easily query if or if not
+ non-generic address spaces (and which) are supported.
+ This is only supported for C. For C++, a language extension is needed
+ (as mentioned in ISO/IEC DTR 18037; Annex F.2) which is not
+ implemented in GCC up to now. */
+
+ if (!strcmp (lang_hooks.name, "GNU C"))
+ {
+ cpp_define (pfile, "__PGM=__pgm");
+ cpp_define (pfile, "__PGM1=__pgm1");
+ cpp_define (pfile, "__PGM2=__pgm2");
+ cpp_define (pfile, "__PGM3=__pgm3");
+ cpp_define (pfile, "__PGM4=__pgm4");
+ cpp_define (pfile, "__PGM5=__pgm5");
+ cpp_define (pfile, "__PGMX=__pgmx");
+ }
+
/* Define builtin macros so that the user can
easily query if or if not a specific builtin
is available. */
@@ -100,6 +136,8 @@ avr_cpu_cpp_builtins (struct cpp_reader *pfile)
cpp_define (pfile, "__BUILTIN_AVR_WDR");
cpp_define (pfile, "__BUILTIN_AVR_SLEEP");
cpp_define (pfile, "__BUILTIN_AVR_SWAP");
+ cpp_define (pfile, "__BUILTIN_AVR_MAP8");
+ cpp_define (pfile, "__BUILTIN_AVR_MAP16");
cpp_define (pfile, "__BUILTIN_AVR_DELAY_CYCLES");
cpp_define (pfile, "__BUILTIN_AVR_FMUL");
diff --git a/gcc/config/avr/avr-devices.c b/gcc/config/avr/avr-devices.c
index d0dda8536af..8d6e947f129 100644
--- a/gcc/config/avr/avr-devices.c
+++ b/gcc/config/avr/avr-devices.c
@@ -23,20 +23,30 @@
#include "coretypes.h"
#include "tm.h"
-/* List of all known AVR MCU architectures. */
+/* List of all known AVR MCU architectures.
+ Order as of enum avr_arch from avr.h. */
-const struct base_arch_s avr_arch_types[] = {
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, NULL, "avr2" }, /* unknown device specified */
- { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, "__AVR_ARCH__=1", "avr1" },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, "__AVR_ARCH__=2", "avr2" },
- { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0x0060, "__AVR_ARCH__=25", "avr25" },
- { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, "__AVR_ARCH__=3", "avr3" },
- { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0x0060, "__AVR_ARCH__=31", "avr31" },
- { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0x0060, "__AVR_ARCH__=35", "avr35" },
- { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0x0060, "__AVR_ARCH__=4", "avr4" },
- { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0x0060, "__AVR_ARCH__=5", "avr5" },
- { 0, 1, 1, 1, 1, 1, 0, 0, 0, 0x0060, "__AVR_ARCH__=51", "avr51" },
- { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0x0060, "__AVR_ARCH__=6", "avr6" }
+const struct base_arch_s
+avr_arch_types[] =
+{
+ /* unknown device specified */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, 1, NULL, "avr2" },
+ /*
+ A M J LM E E E d S S O # F
+ S U M PO L L I a t F ff 6 l
+ M L P MV P P J - - t a R s 4 a
+ XW M M M a r e s
+ X P t t k h */
+ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, 1, "__AVR_ARCH__=1", "avr1" },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, 1, "__AVR_ARCH__=2", "avr2" },
+ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0x0060, 32, 1, "__AVR_ARCH__=25", "avr25" },
+ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, 1, "__AVR_ARCH__=3", "avr3" },
+ { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0x0060, 32, 2, "__AVR_ARCH__=31", "avr31" },
+ { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0x0060, 32, 1, "__AVR_ARCH__=35", "avr35" },
+ { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0x0060, 32, 1, "__AVR_ARCH__=4", "avr4" },
+ { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0x0060, 32, 1, "__AVR_ARCH__=5", "avr5" },
+ { 0, 1, 1, 1, 1, 1, 0, 0, 0, 0x0060, 32, 2, "__AVR_ARCH__=51", "avr51" },
+ { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0x0060, 32, 4, "__AVR_ARCH__=6", "avr6" }
};
const struct mcu_type_s avr_mcu_types[] = {
diff --git a/gcc/config/avr/avr-log.c b/gcc/config/avr/avr-log.c
index cdeb6690fde..3c4bccfa282 100644
--- a/gcc/config/avr/avr-log.c
+++ b/gcc/config/avr/avr-log.c
@@ -49,6 +49,8 @@
C: enum rtx_code
m: enum machine_mode
R: enum reg_class
+ D: double_int (signed decimal)
+ X: double_int (unsigned hex)
L: insn list
H: location_t
@@ -59,6 +61,8 @@
F: caller (via __FUNCTION__)
P: Pass name and number
?: Print caller, current function and pass info
+ !: Ditto, but only print if in a pass with static pass number,
+ else return.
== same as printf ==
@@ -80,9 +84,9 @@ static void avr_log_vadump (FILE*, const char*, va_list);
/* As we have no variadic macros, avr_edump maps to a call to
avr_log_set_caller_e which saves __FUNCTION__ to avr_log_caller and
- returns a function pointer to avr_log_fdump_e. avr_fdump_e
+ returns a function pointer to avr_log_fdump_e. avr_log_fdump_e
gets the printf-like arguments and calls avr_log_vadump, the
- worker function. avr_fdump works the same way. */
+ worker function. avr_fdump works the same way. */
/* Provide avr_log_fdump_e/f so that avr_log_set_caller_e/_f can return
their address. */
@@ -133,6 +137,49 @@ avr_log_set_caller_f (const char *caller)
return avr_log_fdump_f;
}
+
+/* Copy-paste from double-int.c:double_int_split_digit (it's static there).
+ Splits last digit of *CST (taken as unsigned) in BASE and returns it. */
+
+static unsigned
+avr_double_int_pop_digit (double_int *cst, unsigned base)
+{
+ unsigned HOST_WIDE_INT resl, reml;
+ HOST_WIDE_INT resh, remh;
+
+ div_and_round_double (FLOOR_DIV_EXPR, true, cst->low, cst->high, base, 0,
+ &resl, &resh, &reml, &remh);
+ cst->high = resh;
+ cst->low = resl;
+
+ return reml;
+}
+
+
+/* Dump VAL as hex value to FILE. */
+
+static void
+avr_dump_double_int_hex (FILE *file, double_int val)
+{
+ unsigned digit[4];
+
+ digit[0] = avr_double_int_pop_digit (&val, 1 << 16);
+ digit[1] = avr_double_int_pop_digit (&val, 1 << 16);
+ digit[2] = avr_double_int_pop_digit (&val, 1 << 16);
+ digit[3] = avr_double_int_pop_digit (&val, 1 << 16);
+
+ fprintf (file, "0x");
+
+ if (digit[3] | digit[2])
+ fprintf (file, "%04x%04x", digit[3], digit[2]);
+
+ if (digit[3] | digit[2] | digit[1] | digit[0])
+ fprintf (file, "%04x%04x", digit[1], digit[0]);
+ else
+ fprintf (file, "0");
+}
+
+
/* Worker function implementing the %-codes and forwarding to
respective print/dump function. */
@@ -187,6 +234,14 @@ avr_log_vadump (FILE *file, const char *fmt, va_list ap)
fprintf (file, "%d", va_arg (ap, int));
break;
+ case 'D':
+ dump_double_int (file, va_arg (ap, double_int), false);
+ break;
+
+ case 'X':
+ avr_dump_double_int_hex (file, va_arg (ap, double_int));
+ break;
+
case 'x':
fprintf (file, "%x", va_arg (ap, int));
break;
@@ -249,7 +304,7 @@ avr_log_vadump (FILE *file, const char *fmt, va_list ap)
location_t loc = va_arg (ap, location_t);
if (BUILTINS_LOCATION == loc)
- fprintf (file, "<BUILTIN-LOCATION");
+ fprintf (file, "<BUILTIN-LOCATION>");
else if (UNKNOWN_LOCATION == loc)
fprintf (file, "<UNKNOWN-LOCATION>");
else
@@ -304,27 +359,43 @@ avr_log_vadump (FILE *file, const char *fmt, va_list ap)
void
avr_log_set_avr_log (void)
{
- if (avr_log_details)
+ bool all = TARGET_ALL_DEBUG != 0;
+
+ if (all || avr_log_details)
{
/* Adding , at beginning and end of string makes searching easier. */
char *str = (char*) alloca (3 + strlen (avr_log_details));
+ bool info;
str[0] = ',';
strcat (stpcpy (str+1, avr_log_details), ",");
-
-#define SET_DUMP_DETAIL(S) \
- avr_log.S = (TARGET_ALL_DEBUG \
- || NULL != strstr (str, "," #S ",") \
- || NULL != strstr (str, ",all,"))
- SET_DUMP_DETAIL (rtx_costs);
+ all |= NULL != strstr (str, ",all,");
+ info = NULL != strstr (str, ",?,");
+
+ if (info)
+ fprintf (stderr, "\n-mlog=");
+
+#define SET_DUMP_DETAIL(S) \
+ do { \
+ avr_log.S = (all || NULL != strstr (str, "," #S ",")); \
+ if (info) \
+ fprintf (stderr, #S ","); \
+ } while (0)
+
+ SET_DUMP_DETAIL (address_cost);
+ SET_DUMP_DETAIL (builtin);
+ SET_DUMP_DETAIL (constraints);
SET_DUMP_DETAIL (legitimate_address_p);
SET_DUMP_DETAIL (legitimize_address);
SET_DUMP_DETAIL (legitimize_reload_address);
- SET_DUMP_DETAIL (constraints);
- SET_DUMP_DETAIL (address_cost);
+ SET_DUMP_DETAIL (progmem);
+ SET_DUMP_DETAIL (rtx_costs);
#undef SET_DUMP_DETAIL
+
+ if (info)
+ fprintf (stderr, "?\n\n");
}
}
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index d3518335a00..bafd794a302 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -32,7 +32,9 @@ 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 void avr_register_target_pragmas (void);
extern bool avr_accumulate_outgoing_args (void);
+extern void avr_init_expanders (void);
#ifdef TREE_CODE
extern void avr_asm_output_aligned_decl_common (FILE*, const_tree, const char*, unsigned HOST_WIDE_INT, unsigned int, bool);
@@ -47,15 +49,8 @@ extern void init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
#endif /* TREE_CODE */
#ifdef RTX_CODE
-extern void asm_output_external_libcall (FILE *file, rtx symref);
extern const char *output_movqi (rtx insn, rtx operands[], int *l);
extern const char *output_movhi (rtx insn, rtx operands[], int *l);
-extern const char *out_movqi_r_mr (rtx insn, rtx op[], int *l);
-extern const char *out_movqi_mr_r (rtx insn, rtx op[], int *l);
-extern const char *out_movhi_r_mr (rtx insn, rtx op[], int *l);
-extern const char *out_movhi_mr_r (rtx insn, rtx op[], int *l);
-extern const char *out_movsi_r_mr (rtx insn, rtx op[], int *l);
-extern const char *out_movsi_mr_r (rtx insn, rtx op[], int *l);
extern const char *output_movsisf (rtx insn, rtx operands[], int *l);
extern const char *avr_out_tstsi (rtx, rtx*, int*);
extern const char *avr_out_tsthi (rtx, rtx*, int*);
@@ -84,6 +79,7 @@ extern bool avr_rotate_bytes (rtx operands[]);
extern void expand_prologue (void);
extern void expand_epilogue (bool);
+extern bool avr_emit_movmemhi (rtx*);
extern int avr_epilogue_uses (int regno);
extern int avr_starting_frame_offset (void);
@@ -94,6 +90,9 @@ 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 const char* avr_out_xload (rtx, rtx*, int*);
+extern const char* avr_out_movmem (rtx, rtx*, int*);
+extern const char* avr_out_map_bits (rtx, rtx*, int*);
extern bool avr_popcount_each_byte (rtx, int, int);
extern int extra_constraint_Q (rtx x);
@@ -121,6 +120,10 @@ extern reg_class_t avr_mode_code_base_reg_class (enum machine_mode, addr_space_t
extern bool avr_regno_mode_code_ok_for_base_p (int, enum machine_mode, addr_space_t, 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 bool avr_mem_pgm_p (rtx);
+extern bool avr_mem_pgmx_p (rtx);
+extern bool avr_load_libgcc_p (rtx);
+extern bool avr_xload_libgcc_p (enum machine_mode);
#endif /* RTX_CODE */
#ifdef REAL_VALUE_TYPE
@@ -139,12 +142,14 @@ extern void avr_log_set_avr_log (void);
typedef struct
{
- unsigned rtx_costs :1;
+ unsigned address_cost :1;
+ unsigned builtin :1;
+ unsigned constraints :1;
unsigned legitimate_address_p :1;
unsigned legitimize_address :1;
unsigned legitimize_reload_address :1;
- unsigned constraints :1;
- unsigned address_cost :1;
+ unsigned progmem :1;
+ unsigned rtx_costs :1;
} avr_log_t;
extern avr_log_t avr_log;
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 65d43b8ca07..bb4a08dad71 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -35,6 +35,7 @@
#include "tree.h"
#include "output.h"
#include "expr.h"
+#include "c-family/c-common.h"
#include "diagnostic-core.h"
#include "obstack.h"
#include "function.h"
@@ -54,11 +55,21 @@
/* Return true if STR starts with PREFIX and false, otherwise. */
#define STR_PREFIX_P(STR,PREFIX) (0 == strncmp (STR, PREFIX, strlen (PREFIX)))
-#define AVR_SECTION_PROGMEM (SECTION_MACH_DEP << 0)
+/* The 4 bits starting at SECTION_MACH_DEP are reverved to store
+ 1 + flash segment where progmem data is to be located.
+ For example, data with __pgm2 is stored as (1+2) * SECTION_MACH_DEP. */
+#define AVR_SECTION_PROGMEM (0xf * SECTION_MACH_DEP)
/* Prototypes for local helper functions. */
+static const char* out_movqi_r_mr (rtx, rtx[], int*);
+static const char* out_movhi_r_mr (rtx, rtx[], int*);
+static const char* out_movsi_r_mr (rtx, rtx[], int*);
+static const char* out_movqi_mr_r (rtx, rtx[], int*);
+static const char* out_movhi_mr_r (rtx, rtx[], int*);
+static const char* out_movsi_mr_r (rtx, rtx[], int*);
+
static int avr_naked_function_p (tree);
static int interrupt_function_p (tree);
static int signal_function_p (tree);
@@ -84,12 +95,28 @@ 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
+/* Implicit target register of LPM instruction (R0) */
+static GTY(()) rtx lpm_reg_rtx;
+
+/* (Implicit) address register of LPM instruction (R31:R30 = Z) */
+static GTY(()) rtx lpm_addr_reg_rtx;
+
/* Temporary register RTX (gen_rtx_REG (QImode, TMP_REGNO)) */
static GTY(()) rtx tmp_reg_rtx;
/* Zeroed register RTX (gen_rtx_REG (QImode, ZERO_REGNO)) */
static GTY(()) rtx zero_reg_rtx;
+/* RAMPZ special function register */
+static GTY(()) rtx rampz_rtx;
+
+/* RTX containing the strings "" and "e", respectively */
+static GTY(()) rtx xstring_empty;
+static GTY(()) rtx xstring_e;
+
+/* RTXs for all general purpose registers as QImode */
+static GTY(()) rtx all_regs_rtx[32];
+
/* AVR register names {"r0", "r1", ..., "r31"} */
static const char *const avr_regnames[] = REGISTER_NAMES;
@@ -106,7 +133,17 @@ const struct mcu_type_s *avr_current_device;
static GTY(()) section *progmem_swtable_section;
/* Unnamed section associated to __attribute__((progmem)) aka. PROGMEM. */
-static GTY(()) section *progmem_section;
+static GTY(()) section *progmem_section[6];
+
+static const char * const progmem_section_prefix[6] =
+ {
+ ".progmem.data",
+ ".progmem1.data",
+ ".progmem2.data",
+ ".progmem3.data",
+ ".progmem4.data",
+ ".progmem5.data"
+ };
/* To track if code will use .bss and/or .data. */
bool avr_need_clear_bss_p = false;
@@ -172,9 +209,6 @@ bool avr_need_copy_data_p = false;
#undef TARGET_FUNCTION_ARG_ADVANCE
#define TARGET_FUNCTION_ARG_ADVANCE avr_function_arg_advance
-#undef TARGET_LEGITIMIZE_ADDRESS
-#define TARGET_LEGITIMIZE_ADDRESS avr_legitimize_address
-
#undef TARGET_RETURN_IN_MEMORY
#define TARGET_RETURN_IN_MEMORY avr_return_in_memory
@@ -189,9 +223,6 @@ bool avr_need_copy_data_p = false;
#undef TARGET_CASE_VALUES_THRESHOLD
#define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
-#undef TARGET_LEGITIMATE_ADDRESS_P
-#define TARGET_LEGITIMATE_ADDRESS_P avr_legitimate_address_p
-
#undef TARGET_FRAME_POINTER_REQUIRED
#define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p
#undef TARGET_CAN_ELIMINATE
@@ -221,6 +252,24 @@ bool avr_need_copy_data_p = false;
#undef TARGET_SCALAR_MODE_SUPPORTED_P
#define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p
+#undef TARGET_ADDR_SPACE_SUBSET_P
+#define TARGET_ADDR_SPACE_SUBSET_P avr_addr_space_subset_p
+
+#undef TARGET_ADDR_SPACE_CONVERT
+#define TARGET_ADDR_SPACE_CONVERT avr_addr_space_convert
+
+#undef TARGET_ADDR_SPACE_ADDRESS_MODE
+#define TARGET_ADDR_SPACE_ADDRESS_MODE avr_addr_space_address_mode
+
+#undef TARGET_ADDR_SPACE_POINTER_MODE
+#define TARGET_ADDR_SPACE_POINTER_MODE avr_addr_space_pointer_mode
+
+#undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
+#define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P avr_addr_space_legitimate_address_p
+
+#undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
+#define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS avr_addr_space_legitimize_address
+
/* Custom function to replace string prefix.
@@ -323,9 +372,6 @@ avr_option_override (void)
avr_current_arch = &avr_arch_types[avr_current_device->arch];
avr_extra_arch_macro = avr_current_device->macro;
- tmp_reg_rtx = gen_rtx_REG (QImode, TMP_REGNO);
- zero_reg_rtx = gen_rtx_REG (QImode, ZERO_REGNO);
-
init_machine_status = avr_init_machine_status;
avr_log_set_avr_log();
@@ -339,6 +385,38 @@ avr_init_machine_status (void)
return ggc_alloc_cleared_machine_function ();
}
+
+/* Implement `INIT_EXPANDERS'. */
+/* The function works like a singleton. */
+
+void
+avr_init_expanders (void)
+{
+ int regno;
+
+ static bool done = false;
+
+ if (done)
+ return;
+ else
+ done = true;
+
+ for (regno = 0; regno < 32; regno ++)
+ all_regs_rtx[regno] = gen_rtx_REG (QImode, regno);
+
+ lpm_reg_rtx = all_regs_rtx[LPM_REGNO];
+ tmp_reg_rtx = all_regs_rtx[TMP_REGNO];
+ zero_reg_rtx = all_regs_rtx[ZERO_REGNO];
+
+ lpm_addr_reg_rtx = gen_rtx_REG (HImode, REG_Z);
+
+ rampz_rtx = gen_rtx_MEM (QImode, GEN_INT (RAMPZ_ADDR));
+
+ xstring_empty = gen_rtx_CONST_STRING (VOIDmode, "");
+ xstring_e = gen_rtx_CONST_STRING (VOIDmode, "e");
+}
+
+
/* Return register class for register R. */
enum reg_class
@@ -384,6 +462,81 @@ avr_scalar_mode_supported_p (enum machine_mode mode)
}
+/* Return the segment number of pgm address space AS, i.e.
+ the 64k block it lives in.
+ Return -1 if unknown, i.e. 24-bit AS in flash.
+ Return -2 for anything else. */
+
+static int
+avr_pgm_segment (addr_space_t as)
+{
+ switch (as)
+ {
+ default: return -2;
+
+ case ADDR_SPACE_PGMX: return -1;
+ case ADDR_SPACE_PGM: return 0;
+ case ADDR_SPACE_PGM1: return 1;
+ case ADDR_SPACE_PGM2: return 2;
+ case ADDR_SPACE_PGM3: return 3;
+ case ADDR_SPACE_PGM4: return 4;
+ case ADDR_SPACE_PGM5: return 5;
+ }
+}
+
+
+/* Return TRUE if DECL is a VAR_DECL located in Flash and FALSE, otherwise. */
+
+static bool
+avr_decl_pgm_p (tree decl)
+{
+ if (TREE_CODE (decl) != VAR_DECL
+ || TREE_TYPE (decl) == error_mark_node)
+ {
+ return false;
+ }
+
+ return !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (decl)));
+}
+
+
+/* Return TRUE if DECL is a VAR_DECL located in the 24-bit Flash
+ address space and FALSE, otherwise. */
+
+static bool
+avr_decl_pgmx_p (tree decl)
+{
+ if (TREE_CODE (decl) != VAR_DECL
+ || TREE_TYPE (decl) == error_mark_node)
+ {
+ return false;
+ }
+
+ return (ADDR_SPACE_PGMX == TYPE_ADDR_SPACE (TREE_TYPE (decl)));
+}
+
+
+/* Return TRUE if X is a MEM rtx located in Flash and FALSE, otherwise. */
+
+bool
+avr_mem_pgm_p (rtx x)
+{
+ return (MEM_P (x)
+ && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x)));
+}
+
+
+/* Return TRUE if X is a MEM rtx located in the 24-bit Flash
+ address space and FALSE, otherwise. */
+
+bool
+avr_mem_pgmx_p (rtx x)
+{
+ return (MEM_P (x)
+ && ADDR_SPACE_PGMX == MEM_ADDR_SPACE (x));
+}
+
+
/* A helper for the subsequent function attribute used to dig for
attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
@@ -989,8 +1142,7 @@ expand_prologue (void)
&& TEST_HARD_REG_BIT (set, REG_Z)
&& TEST_HARD_REG_BIT (set, REG_Z + 1))
{
- emit_move_insn (tmp_reg_rtx,
- gen_rtx_MEM (QImode, GEN_INT (RAMPZ_ADDR)));
+ emit_move_insn (tmp_reg_rtx, rampz_rtx);
emit_push_byte (TMP_REGNO, false);
}
@@ -1228,8 +1380,7 @@ expand_epilogue (bool sibcall_p)
&& 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);
+ emit_move_insn (rampz_rtx, tmp_reg_rtx);
}
/* Restore SREG using tmp reg as scratch. */
@@ -1379,6 +1530,9 @@ avr_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
return ok;
}
+
+/* Former implementation of TARGET_LEGITIMIZE_ADDRESS,
+ now only a helper for avr_addr_space_legitimize_address. */
/* Attempts to replace X with a valid
memory address for an operand of mode MODE */
@@ -1641,8 +1795,9 @@ print_operand_address (FILE *file, rtx addr)
}
-/* Output X as assembler operand to file FILE. */
-
+/* Output X as assembler operand to file FILE.
+ For a description of supported %-codes, see top of avr.md. */
+
void
print_operand (FILE *file, rtx x, int code)
{
@@ -1661,6 +1816,31 @@ print_operand (FILE *file, rtx x, int code)
if (AVR_HAVE_EIJMP_EICALL)
fputc ('e', file);
}
+ else if (code == 't'
+ || code == 'T')
+ {
+ static int t_regno = -1;
+ static int t_nbits = -1;
+
+ if (REG_P (x) && t_regno < 0 && code == 'T')
+ {
+ t_regno = REGNO (x);
+ t_nbits = GET_MODE_BITSIZE (GET_MODE (x));
+ }
+ else if (CONST_INT_P (x) && t_regno >= 0
+ && IN_RANGE (INTVAL (x), 0, t_nbits - 1))
+ {
+ int bpos = INTVAL (x);
+
+ fprintf (file, "%s", reg_names[t_regno + bpos / 8]);
+ if (code == 'T')
+ fprintf (file, ",%d", bpos % 8);
+
+ t_regno = -1;
+ }
+ else
+ fatal_insn ("operands to %T/%t must be reg + const_int:", x);
+ }
else if (REG_P (x))
{
if (x == zero_reg_rtx)
@@ -1668,16 +1848,39 @@ print_operand (FILE *file, rtx x, int code)
else
fprintf (file, reg_names[true_regnum (x) + abcd]);
}
- else if (GET_CODE (x) == CONST_INT)
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + abcd);
- else if (GET_CODE (x) == MEM)
+ else if (CONST_INT_P (x))
+ {
+ HOST_WIDE_INT ival = INTVAL (x);
+
+ if ('i' != code)
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival + abcd);
+ else if (low_io_address_operand (x, VOIDmode)
+ || high_io_address_operand (x, VOIDmode))
+ {
+ switch (ival)
+ {
+ case RAMPZ_ADDR: fprintf (file, "__RAMPZ__"); break;
+ case SREG_ADDR: fprintf (file, "__SREG__"); break;
+ case SP_ADDR: fprintf (file, "__SP_L__"); break;
+ case SP_ADDR+1: fprintf (file, "__SP_H__"); break;
+
+ default:
+ fprintf (file, HOST_WIDE_INT_PRINT_HEX,
+ ival - avr_current_arch->sfr_offset);
+ break;
+ }
+ }
+ else
+ fatal_insn ("bad address, not an I/O address:", x);
+ }
+ else if (MEM_P (x))
{
rtx addr = XEXP (x, 0);
if (code == 'm')
{
if (!CONSTANT_P (addr))
- fatal_insn ("bad address, not a constant):", 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"
@@ -1688,6 +1891,10 @@ print_operand (FILE *file, rtx x, int code)
}
output_addr_const (file, addr);
}
+ else if (code == 'i')
+ {
+ print_operand (file, addr, 'i');
+ }
else if (code == 'o')
{
if (GET_CODE (addr) != PLUS)
@@ -1717,6 +1924,10 @@ print_operand (FILE *file, rtx x, int code)
else
print_operand_address (file, addr);
}
+ else if (code == 'i')
+ {
+ fatal_insn ("bad address, not an I/O address:", x);
+ }
else if (code == 'x')
{
/* Constant progmem address - like used in jmp or call */
@@ -1740,6 +1951,8 @@ print_operand (FILE *file, rtx x, int code)
REAL_VALUE_TO_TARGET_SINGLE (rv, val);
fprintf (file, "0x%lx", val);
}
+ else if (GET_CODE (x) == CONST_STRING)
+ fputs (XSTR (x, 0), file);
else if (code == 'j')
fputs (cond_string (GET_CODE (x)), file);
else if (code == 'k')
@@ -2177,6 +2390,436 @@ avr_function_ok_for_sibcall (tree decl_callee, tree exp_callee)
/***********************************************************************
Functions for outputting various mov's for a various modes
************************************************************************/
+
+/* Return true if a value of mode MODE is read from flash by
+ __load_* function from libgcc. */
+
+bool
+avr_load_libgcc_p (rtx op)
+{
+ enum machine_mode mode = GET_MODE (op);
+ int n_bytes = GET_MODE_SIZE (mode);
+
+ return (n_bytes > 2
+ && !AVR_HAVE_LPMX
+ && avr_mem_pgm_p (op));
+}
+
+/* Return true if a value of mode MODE is read by __xload_* function. */
+
+bool
+avr_xload_libgcc_p (enum machine_mode mode)
+{
+ int n_bytes = GET_MODE_SIZE (mode);
+
+ return (n_bytes > 1
+ && avr_current_arch->n_segments > 1
+ && !AVR_HAVE_ELPMX);
+}
+
+
+/* Find an unused d-register to be used as scratch in INSN.
+ EXCLUDE is either NULL_RTX or some register. In the case where EXCLUDE
+ is a register, skip all possible return values that overlap EXCLUDE.
+ The policy for the returned register is similar to that of
+ `reg_unused_after', i.e. the returned register may overlap the SET_DEST
+ of INSN.
+
+ Return a QImode d-register or NULL_RTX if nothing found. */
+
+static rtx
+avr_find_unused_d_reg (rtx insn, rtx exclude)
+{
+ int regno;
+ bool isr_p = (interrupt_function_p (current_function_decl)
+ || signal_function_p (current_function_decl));
+
+ for (regno = 16; regno < 32; regno++)
+ {
+ rtx reg = all_regs_rtx[regno];
+
+ if ((exclude
+ && reg_overlap_mentioned_p (exclude, reg))
+ || fixed_regs[regno])
+ {
+ continue;
+ }
+
+ /* Try non-live register */
+
+ if (!df_regs_ever_live_p (regno)
+ && (TREE_THIS_VOLATILE (current_function_decl)
+ || cfun->machine->is_OS_task
+ || cfun->machine->is_OS_main
+ || (!isr_p && call_used_regs[regno])))
+ {
+ return reg;
+ }
+
+ /* Any live register can be used if it is unused after.
+ Prologue/epilogue will care for it as needed. */
+
+ if (df_regs_ever_live_p (regno)
+ && reg_unused_after (insn, reg))
+ {
+ return reg;
+ }
+ }
+
+ return NULL_RTX;
+}
+
+
+/* Helper function for the next function in the case where only restricted
+ version of LPM instruction is available. */
+
+static const char*
+avr_out_lpm_no_lpmx (rtx insn, rtx *xop, int *plen)
+{
+ rtx dest = xop[0];
+ rtx addr = xop[1];
+ int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
+ int regno_dest;
+
+ regno_dest = REGNO (dest);
+
+ /* The implicit target register of LPM. */
+ xop[3] = lpm_reg_rtx;
+
+ switch (GET_CODE (addr))
+ {
+ default:
+ gcc_unreachable();
+
+ case REG:
+
+ gcc_assert (REG_Z == REGNO (addr));
+
+ switch (n_bytes)
+ {
+ default:
+ gcc_unreachable();
+
+ case 1:
+ avr_asm_len ("%4lpm", xop, plen, 1);
+
+ if (regno_dest != LPM_REGNO)
+ avr_asm_len ("mov %0,%3", xop, plen, 1);
+
+ return "";
+
+ case 2:
+ if (REGNO (dest) == REG_Z)
+ return avr_asm_len ("%4lpm" CR_TAB
+ "push %3" CR_TAB
+ "adiw %2,1" CR_TAB
+ "%4lpm" CR_TAB
+ "mov %B0,%3" CR_TAB
+ "pop %A0", xop, plen, 6);
+
+ avr_asm_len ("%4lpm" CR_TAB
+ "mov %A0,%3" CR_TAB
+ "adiw %2,1" CR_TAB
+ "%4lpm" CR_TAB
+ "mov %B0,%3", xop, plen, 5);
+
+ if (!reg_unused_after (insn, addr))
+ avr_asm_len ("sbiw %2,1", xop, plen, 1);
+
+ break; /* 2 */
+ }
+
+ break; /* REG */
+
+ case POST_INC:
+
+ gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
+ && n_bytes <= 4);
+
+ if (regno_dest == LPM_REGNO)
+ avr_asm_len ("%4lpm" CR_TAB
+ "adiw %2,1", xop, plen, 2);
+ else
+ avr_asm_len ("%4lpm" CR_TAB
+ "mov %A0,%3" CR_TAB
+ "adiw %2,1", xop, plen, 3);
+
+ if (n_bytes >= 2)
+ avr_asm_len ("%4lpm" CR_TAB
+ "mov %B0,%3" CR_TAB
+ "adiw %2,1", xop, plen, 3);
+
+ if (n_bytes >= 3)
+ avr_asm_len ("%4lpm" CR_TAB
+ "mov %C0,%3" CR_TAB
+ "adiw %2,1", xop, plen, 3);
+
+ if (n_bytes >= 4)
+ avr_asm_len ("%4lpm" CR_TAB
+ "mov %D0,%3" CR_TAB
+ "adiw %2,1", xop, plen, 3);
+
+ break; /* POST_INC */
+
+ } /* switch CODE (addr) */
+
+ return "";
+}
+
+
+/* If PLEN == NULL: Ouput instructions to load a value from a memory location
+ OP[1] in AS1 to register OP[0].
+ If PLEN != 0 set *PLEN to the length in words of the instruction sequence.
+ Return "". */
+
+static const char*
+avr_out_lpm (rtx insn, rtx *op, int *plen)
+{
+ rtx xop[6];
+ rtx dest = op[0];
+ rtx src = SET_SRC (single_set (insn));
+ rtx addr;
+ int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
+ int regno_dest;
+ int segment;
+
+ if (plen)
+ *plen = 0;
+
+ if (MEM_P (dest))
+ {
+ warning (0, "writing to address space %qs not supported",
+ c_addr_space_name (MEM_ADDR_SPACE (dest)));
+
+ return "";
+ }
+
+ addr = XEXP (src, 0);
+
+ segment = avr_pgm_segment (MEM_ADDR_SPACE (src));
+
+ gcc_assert (REG_P (dest)
+ && ((segment >= 0
+ && (REG_P (addr) || POST_INC == GET_CODE (addr)))
+ || (GET_CODE (addr) == LO_SUM && segment == -1)));
+
+ if (segment == -1)
+ {
+ /* We are called from avr_out_xload because someone wrote
+ __pgmx on a device with just one flash segment. */
+
+ addr = XEXP (addr, 1);
+ }
+
+ xop[0] = dest;
+ xop[1] = addr;
+ xop[2] = lpm_addr_reg_rtx;
+ xop[4] = xstring_empty;
+ xop[5] = tmp_reg_rtx;
+
+ regno_dest = REGNO (dest);
+
+ /* Cut down segment number to a number the device actually
+ supports. We do this late to preserve the address space's
+ name for diagnostics. */
+
+ segment %= avr_current_arch->n_segments;
+
+ /* Set RAMPZ as needed. */
+
+ if (segment)
+ {
+ xop[4] = GEN_INT (segment);
+
+ if (xop[3] = avr_find_unused_d_reg (insn, lpm_addr_reg_rtx),
+ xop[3])
+ {
+ avr_asm_len ("ldi %3,%4" CR_TAB
+ "out __RAMPZ__,%3", xop, plen, 2);
+ }
+ else if (segment == 1)
+ {
+ avr_asm_len ("clr %5" CR_TAB
+ "inc %5" CR_TAB
+ "out __RAMPZ__,%5", xop, plen, 3);
+ }
+ else
+ {
+ avr_asm_len ("mov %5,%2" CR_TAB
+ "ldi %2,%4" CR_TAB
+ "out __RAMPZ__,%2" CR_TAB
+ "mov %2,%5", xop, plen, 4);
+ }
+
+ xop[4] = xstring_e;
+ }
+
+ if ((segment == 0 && !AVR_HAVE_LPMX)
+ || (segment != 0 && !AVR_HAVE_ELPMX))
+ {
+ return avr_out_lpm_no_lpmx (insn, xop, plen);
+ }
+
+ switch (GET_CODE (addr))
+ {
+ default:
+ gcc_unreachable();
+
+ case REG:
+
+ gcc_assert (REG_Z == REGNO (addr));
+
+ switch (n_bytes)
+ {
+ default:
+ gcc_unreachable();
+
+ case 1:
+ return avr_asm_len ("%4lpm %0,%a2", xop, plen, 1);
+
+ case 2:
+ if (REGNO (dest) == REG_Z)
+ return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
+ "%4lpm %B0,%a2" CR_TAB
+ "mov %A0,%5", xop, plen, 3);
+ else
+ {
+ avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
+ "%4lpm %B0,%a2", xop, plen, 2);
+
+ if (!reg_unused_after (insn, addr))
+ avr_asm_len ("sbiw %2,1", xop, plen, 1);
+ }
+
+ break; /* 2 */
+
+ case 3:
+
+ avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
+ "%4lpm %B0,%a2+" CR_TAB
+ "%4lpm %C0,%a2", xop, plen, 3);
+
+ if (!reg_unused_after (insn, addr))
+ avr_asm_len ("sbiw %2,2", xop, plen, 1);
+
+ break; /* 3 */
+
+ case 4:
+
+ avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
+ "%4lpm %B0,%a2+", xop, plen, 2);
+
+ if (REGNO (dest) == REG_Z - 2)
+ return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
+ "%4lpm %C0,%a2" CR_TAB
+ "mov %D0,%5", xop, plen, 3);
+ else
+ {
+ avr_asm_len ("%4lpm %C0,%a2+" CR_TAB
+ "%4lpm %D0,%a2", xop, plen, 2);
+
+ if (!reg_unused_after (insn, addr))
+ avr_asm_len ("sbiw %2,3", xop, plen, 1);
+ }
+
+ break; /* 4 */
+ } /* n_bytes */
+
+ break; /* REG */
+
+ case POST_INC:
+
+ gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
+ && n_bytes <= 4);
+
+ avr_asm_len ("%4lpm %A0,%a2+", xop, plen, 1);
+ if (n_bytes >= 2) avr_asm_len ("%4lpm %B0,%a2+", xop, plen, 1);
+ if (n_bytes >= 3) avr_asm_len ("%4lpm %C0,%a2+", xop, plen, 1);
+ if (n_bytes >= 4) avr_asm_len ("%4lpm %D0,%a2+", xop, plen, 1);
+
+ break; /* POST_INC */
+
+ } /* switch CODE (addr) */
+
+ return "";
+}
+
+
+/* Worker function for xload_<mode> and xload_8 insns. */
+
+const char*
+avr_out_xload (rtx insn, rtx *op, int *plen)
+{
+ rtx xop[5];
+ rtx reg = op[0];
+ int n_bytes = GET_MODE_SIZE (GET_MODE (reg));
+ unsigned int regno = REGNO (reg);
+
+ if (avr_current_arch->n_segments == 1)
+ return avr_out_lpm (insn, op, plen);
+
+ xop[0] = reg;
+ xop[1] = op[1];
+ xop[2] = lpm_addr_reg_rtx;
+ xop[3] = lpm_reg_rtx;
+ xop[4] = tmp_reg_rtx;
+
+ avr_asm_len ("out __RAMPZ__,%1", xop, plen, -1);
+
+ if (1 == n_bytes)
+ {
+ if (AVR_HAVE_ELPMX)
+ return avr_asm_len ("elpm %0,%a2", xop, plen, 1);
+ else
+ return avr_asm_len ("elpm" CR_TAB
+ "mov %0,%3", xop, plen, 2);
+ }
+
+ gcc_assert (AVR_HAVE_ELPMX);
+
+ if (!reg_overlap_mentioned_p (reg, lpm_addr_reg_rtx))
+ {
+ /* Insn clobbers the Z-register so we can use post-increment. */
+
+ avr_asm_len ("elpm %A0,%a2+", xop, plen, 1);
+ if (n_bytes >= 2) avr_asm_len ("elpm %B0,%a2+", xop, plen, 1);
+ if (n_bytes >= 3) avr_asm_len ("elpm %C0,%a2+", xop, plen, 1);
+ if (n_bytes >= 4) avr_asm_len ("elpm %D0,%a2+", xop, plen, 1);
+
+ return "";
+ }
+
+ switch (n_bytes)
+ {
+ default:
+ gcc_unreachable();
+
+ case 2:
+ gcc_assert (regno == REGNO (lpm_addr_reg_rtx));
+
+ return avr_asm_len ("elpm %4,%a2+" CR_TAB
+ "elpm %B0,%a2" CR_TAB
+ "mov %A0,%4", xop, plen, 3);
+
+ case 3:
+ case 4:
+ gcc_assert (regno + 2 == REGNO (lpm_addr_reg_rtx));
+
+ avr_asm_len ("elpm %A0,%a2+" CR_TAB
+ "elpm %B0,%a2+", xop, plen, 2);
+
+ if (n_bytes == 3)
+ return avr_asm_len ("elpm %C0,%a2", xop, plen, 1);
+ else
+ return avr_asm_len ("elpm %4,%a2+" CR_TAB
+ "elpm %D0,%a2" CR_TAB
+ "mov %C0,%4", xop, plen, 3);
+ }
+
+ return "";
+}
+
+
const char *
output_movqi (rtx insn, rtx operands[], int *l)
{
@@ -2185,6 +2828,12 @@ output_movqi (rtx insn, rtx operands[], int *l)
rtx src = operands[1];
int *real_l = l;
+ if (avr_mem_pgm_p (src)
+ || avr_mem_pgm_p (dest))
+ {
+ return avr_out_lpm (insn, operands, real_l);
+ }
+
if (!l)
l = &dummy;
@@ -2211,17 +2860,12 @@ output_movqi (rtx insn, rtx operands[], int *l)
}
else if (GET_CODE (dest) == MEM)
{
- const char *templ;
-
- if (src == const0_rtx)
- operands[1] = zero_reg_rtx;
-
- templ = out_movqi_mr_r (insn, operands, real_l);
+ rtx xop[2];
- if (!real_l)
- output_asm_insn (templ, operands);
+ xop[0] = dest;
+ xop[1] = src == const0_rtx ? zero_reg_rtx : src;
- operands[1] = src;
+ return out_movqi_mr_r (insn, xop, real_l);
}
return "";
}
@@ -2235,6 +2879,12 @@ output_movhi (rtx insn, rtx operands[], int *l)
rtx src = operands[1];
int *real_l = l;
+ if (avr_mem_pgm_p (src)
+ || avr_mem_pgm_p (dest))
+ {
+ return avr_out_lpm (insn, operands, real_l);
+ }
+
if (!l)
l = &dummy;
@@ -2286,93 +2936,79 @@ output_movhi (rtx insn, rtx operands[], int *l)
}
else if (GET_CODE (dest) == MEM)
{
- const char *templ;
-
- if (src == const0_rtx)
- operands[1] = zero_reg_rtx;
-
- templ = out_movhi_mr_r (insn, operands, real_l);
+ rtx xop[2];
- if (!real_l)
- output_asm_insn (templ, operands);
+ xop[0] = dest;
+ xop[1] = src == const0_rtx ? zero_reg_rtx : src;
- operands[1] = src;
- return "";
+ return out_movhi_mr_r (insn, xop, real_l);
}
fatal_insn ("invalid insn:", insn);
return "";
}
-const char *
-out_movqi_r_mr (rtx insn, rtx op[], int *l)
+static const char*
+out_movqi_r_mr (rtx insn, rtx op[], int *plen)
{
rtx dest = op[0];
rtx src = op[1];
rtx x = XEXP (src, 0);
- int dummy;
-
- if (!l)
- l = &dummy;
if (CONSTANT_ADDRESS_P (x))
{
- if (CONST_INT_P (x) && INTVAL (x) == SREG_ADDR)
- {
- *l = 1;
- return AS2 (in,%0,__SREG__);
- }
- if (optimize > 0 && io_address_operand (x, QImode))
- {
- *l = 1;
- return AS2 (in,%0,%m1-0x20);
- }
- *l = 2;
- return AS2 (lds,%0,%m1);
+ return optimize > 0 && io_address_operand (x, QImode)
+ ? avr_asm_len ("in %0,%i1", op, plen, -1)
+ : avr_asm_len ("lds %0,%m1", op, plen, -2);
}
- /* memory access by reg+disp */
else if (GET_CODE (x) == PLUS
- && REG_P (XEXP (x,0))
- && GET_CODE (XEXP (x,1)) == CONST_INT)
+ && REG_P (XEXP (x, 0))
+ && CONST_INT_P (XEXP (x, 1)))
{
- if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63)
- {
- int disp = INTVAL (XEXP (x,1));
- if (REGNO (XEXP (x,0)) != REG_Y)
- fatal_insn ("incorrect insn:",insn);
+ /* memory access by reg+disp */
- if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
- return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
- AS2 (ldd,%0,Y+63) CR_TAB
- AS2 (sbiw,r28,%o1-63));
+ int disp = INTVAL (XEXP (x, 1));
+
+ if (disp - GET_MODE_SIZE (GET_MODE (src)) >= 63)
+ {
+ if (REGNO (XEXP (x, 0)) != REG_Y)
+ fatal_insn ("incorrect insn:",insn);
- return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
- AS2 (sbci,r29,hi8(-%o1)) CR_TAB
- AS2 (ld,%0,Y) CR_TAB
- AS2 (subi,r28,lo8(%o1)) CR_TAB
- AS2 (sbci,r29,hi8(%o1)));
- }
- else if (REGNO (XEXP (x,0)) == REG_X)
- {
- /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
- it but I have this situation with extremal optimizing options. */
- if (reg_overlap_mentioned_p (dest, XEXP (x,0))
- || reg_unused_after (insn, XEXP (x,0)))
- return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB
- AS2 (ld,%0,X));
-
- return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
- AS2 (ld,%0,X) CR_TAB
- AS2 (sbiw,r26,%o1));
- }
- *l = 1;
- return AS2 (ldd,%0,%1);
+ if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
+ return avr_asm_len ("adiw r28,%o1-63" CR_TAB
+ "ldd %0,Y+63" CR_TAB
+ "sbiw r28,%o1-63", op, plen, -3);
+
+ return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
+ "sbci r29,hi8(-%o1)" CR_TAB
+ "ld %0,Y" CR_TAB
+ "subi r28,lo8(%o1)" CR_TAB
+ "sbci r29,hi8(%o1)", op, plen, -5);
+ }
+ else if (REGNO (XEXP (x, 0)) == REG_X)
+ {
+ /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
+ it but I have this situation with extremal optimizing options. */
+
+ avr_asm_len ("adiw r26,%o1" CR_TAB
+ "ld %0,X", op, plen, -2);
+
+ if (!reg_overlap_mentioned_p (dest, XEXP (x,0))
+ && !reg_unused_after (insn, XEXP (x,0)))
+ {
+ avr_asm_len ("sbiw r26,%o1", op, plen, 1);
+ }
+
+ return "";
+ }
+
+ return avr_asm_len ("ldd %0,%1", op, plen, -1);
}
- *l = 1;
- return AS2 (ld,%0,%1);
+
+ return avr_asm_len ("ld %0,%1", op, plen, -1);
}
-const char *
-out_movhi_r_mr (rtx insn, rtx op[], int *l)
+static const char*
+out_movhi_r_mr (rtx insn, rtx op[], int *plen)
{
rtx dest = op[0];
rtx src = op[1];
@@ -2382,39 +3018,25 @@ out_movhi_r_mr (rtx insn, rtx op[], int *l)
/* "volatile" forces reading low byte first, even if less efficient,
for correct operation with 16-bit I/O registers. */
int mem_volatile_p = MEM_VOLATILE_P (src);
- int tmp;
-
- if (!l)
- l = &tmp;
if (reg_base > 0)
{
if (reg_dest == reg_base) /* R = (R) */
- {
- *l = 3;
- return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
- AS2 (ld,%B0,%1) CR_TAB
- AS2 (mov,%A0,__tmp_reg__));
- }
- else if (reg_base == REG_X) /* (R26) */
- {
- if (reg_unused_after (insn, base))
- {
- *l = 2;
- return (AS2 (ld,%A0,X+) CR_TAB
- AS2 (ld,%B0,X));
- }
- *l = 3;
- return (AS2 (ld,%A0,X+) CR_TAB
- AS2 (ld,%B0,X) CR_TAB
- AS2 (sbiw,r26,1));
- }
- else /* (R) */
- {
- *l = 2;
- return (AS2 (ld,%A0,%1) CR_TAB
- AS2 (ldd,%B0,%1+1));
- }
+ return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
+ "ld %B0,%1" CR_TAB
+ "mov %A0,__tmp_reg__", op, plen, -3);
+
+ if (reg_base != REG_X)
+ return avr_asm_len ("ld %A0,%1" CR_TAB
+ "ldd %B0,%1+1", op, plen, -2);
+
+ avr_asm_len ("ld %A0,X+" CR_TAB
+ "ld %B0,X", op, plen, -2);
+
+ if (!reg_unused_after (insn, base))
+ avr_asm_len ("sbiw r26,1", op, plen, 1);
+
+ return "";
}
else if (GET_CODE (base) == PLUS) /* (R + i) */
{
@@ -2422,109 +3044,90 @@ out_movhi_r_mr (rtx insn, rtx op[], int *l)
int reg_base = true_regnum (XEXP (base, 0));
if (disp > MAX_LD_OFFSET (GET_MODE (src)))
- {
- if (REGNO (XEXP (base, 0)) != REG_Y)
- fatal_insn ("incorrect insn:",insn);
-
- if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
- return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
- AS2 (ldd,%A0,Y+62) CR_TAB
- AS2 (ldd,%B0,Y+63) CR_TAB
- AS2 (sbiw,r28,%o1-62));
+ {
+ if (REGNO (XEXP (base, 0)) != REG_Y)
+ fatal_insn ("incorrect insn:",insn);
+
+ return disp <= 63 + MAX_LD_OFFSET (GET_MODE (src))
+ ? avr_asm_len ("adiw r28,%o1-62" CR_TAB
+ "ldd %A0,Y+62" CR_TAB
+ "ldd %B0,Y+63" CR_TAB
+ "sbiw r28,%o1-62", op, plen, -4)
+
+ : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
+ "sbci r29,hi8(-%o1)" CR_TAB
+ "ld %A0,Y" CR_TAB
+ "ldd %B0,Y+1" CR_TAB
+ "subi r28,lo8(%o1)" CR_TAB
+ "sbci r29,hi8(%o1)", op, plen, -6);
+ }
+
+ /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
+ it but I have this situation with extremal
+ optimization options. */
- return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
- AS2 (sbci,r29,hi8(-%o1)) CR_TAB
- AS2 (ld,%A0,Y) CR_TAB
- AS2 (ldd,%B0,Y+1) CR_TAB
- AS2 (subi,r28,lo8(%o1)) CR_TAB
- AS2 (sbci,r29,hi8(%o1)));
- }
if (reg_base == REG_X)
- {
- /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
- it but I have this situation with extremal
- optimization options. */
-
- *l = 4;
- if (reg_base == reg_dest)
- return (AS2 (adiw,r26,%o1) CR_TAB
- AS2 (ld,__tmp_reg__,X+) CR_TAB
- AS2 (ld,%B0,X) CR_TAB
- AS2 (mov,%A0,__tmp_reg__));
+ return reg_base == reg_dest
+ ? avr_asm_len ("adiw r26,%o1" CR_TAB
+ "ld __tmp_reg__,X+" CR_TAB
+ "ld %B0,X" CR_TAB
+ "mov %A0,__tmp_reg__", op, plen, -4)
- return (AS2 (adiw,r26,%o1) CR_TAB
- AS2 (ld,%A0,X+) CR_TAB
- AS2 (ld,%B0,X) CR_TAB
- AS2 (sbiw,r26,%o1+1));
- }
+ : avr_asm_len ("adiw r26,%o1" CR_TAB
+ "ld %A0,X+" CR_TAB
+ "ld %B0,X" CR_TAB
+ "sbiw r26,%o1+1", op, plen, -4);
- if (reg_base == reg_dest)
- {
- *l = 3;
- return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
- AS2 (ldd,%B0,%B1) CR_TAB
- AS2 (mov,%A0,__tmp_reg__));
- }
-
- *l = 2;
- return (AS2 (ldd,%A0,%A1) CR_TAB
- AS2 (ldd,%B0,%B1));
+ return reg_base == reg_dest
+ ? avr_asm_len ("ldd __tmp_reg__,%A1" CR_TAB
+ "ldd %B0,%B1" CR_TAB
+ "mov %A0,__tmp_reg__", op, plen, -3)
+
+ : avr_asm_len ("ldd %A0,%A1" CR_TAB
+ "ldd %B0,%B1", op, plen, -2);
}
else if (GET_CODE (base) == PRE_DEC) /* (--R) */
{
if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
- fatal_insn ("incorrect insn:", insn);
+ fatal_insn ("incorrect insn:", insn);
- if (mem_volatile_p)
- {
- if (REGNO (XEXP (base, 0)) == REG_X)
- {
- *l = 4;
- return (AS2 (sbiw,r26,2) CR_TAB
- AS2 (ld,%A0,X+) CR_TAB
- AS2 (ld,%B0,X) CR_TAB
- AS2 (sbiw,r26,1));
- }
- else
- {
- *l = 3;
- return (AS2 (sbiw,%r1,2) CR_TAB
- AS2 (ld,%A0,%p1) CR_TAB
- AS2 (ldd,%B0,%p1+1));
- }
- }
-
- *l = 2;
- return (AS2 (ld,%B0,%1) CR_TAB
- AS2 (ld,%A0,%1));
+ if (!mem_volatile_p)
+ return avr_asm_len ("ld %B0,%1" CR_TAB
+ "ld %A0,%1", op, plen, -2);
+
+ return REGNO (XEXP (base, 0)) == REG_X
+ ? avr_asm_len ("sbiw r26,2" CR_TAB
+ "ld %A0,X+" CR_TAB
+ "ld %B0,X" CR_TAB
+ "sbiw r26,1", op, plen, -4)
+
+ : avr_asm_len ("sbiw %r1,2" CR_TAB
+ "ld %A0,%p1" CR_TAB
+ "ldd %B0,%p1+1", op, plen, -3);
}
else if (GET_CODE (base) == POST_INC) /* (R++) */
{
if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
- fatal_insn ("incorrect insn:", insn);
+ fatal_insn ("incorrect insn:", insn);
- *l = 2;
- return (AS2 (ld,%A0,%1) CR_TAB
- AS2 (ld,%B0,%1));
+ return avr_asm_len ("ld %A0,%1" CR_TAB
+ "ld %B0,%1", op, plen, -2);
}
else if (CONSTANT_ADDRESS_P (base))
{
- if (optimize > 0 && io_address_operand (base, HImode))
- {
- *l = 2;
- return (AS2 (in,%A0,%m1-0x20) CR_TAB
- AS2 (in,%B0,%m1+1-0x20));
- }
- *l = 4;
- return (AS2 (lds,%A0,%m1) CR_TAB
- AS2 (lds,%B0,%m1+1));
+ return optimize > 0 && io_address_operand (base, HImode)
+ ? avr_asm_len ("in %A0,%i1" CR_TAB
+ "in %B0,%i1+1", op, plen, -2)
+
+ : avr_asm_len ("lds %A0,%m1" CR_TAB
+ "lds %B0,%m1+1", op, plen, -4);
}
fatal_insn ("unknown move insn:",insn);
return "";
}
-const char *
+static const char*
out_movsi_r_mr (rtx insn, rtx op[], int *l)
{
rtx dest = op[0];
@@ -2685,7 +3288,7 @@ out_movsi_r_mr (rtx insn, rtx op[], int *l)
return "";
}
-const char *
+static const char*
out_movsi_mr_r (rtx insn, rtx op[], int *l)
{
rtx dest = op[0];
@@ -2848,6 +3451,12 @@ output_movsisf (rtx insn, rtx operands[], int *l)
rtx src = operands[1];
int *real_l = l;
+ if (avr_mem_pgm_p (src)
+ || avr_mem_pgm_p (dest))
+ {
+ return avr_out_lpm (insn, operands, real_l);
+ }
+
if (!l)
l = &dummy;
@@ -2884,34 +3493,10 @@ output_movsisf (rtx insn, rtx operands[], int *l)
AS2 (mov,%D0,%D1));
}
}
- else if (CONST_INT_P (src)
- || CONST_DOUBLE_P (src))
- {
- return output_reload_insisf (operands, NULL_RTX, real_l);
- }
else if (CONSTANT_P (src))
{
- if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
- {
- *l = 4;
- return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
- AS2 (ldi,%B0,hi8(%1)) CR_TAB
- AS2 (ldi,%C0,hlo8(%1)) CR_TAB
- AS2 (ldi,%D0,hhi8(%1)));
- }
- /* Last resort, better than loading from memory. */
- *l = 10;
- return (AS2 (mov,__tmp_reg__,r31) CR_TAB
- AS2 (ldi,r31,lo8(%1)) CR_TAB
- AS2 (mov,%A0,r31) CR_TAB
- AS2 (ldi,r31,hi8(%1)) CR_TAB
- AS2 (mov,%B0,r31) CR_TAB
- AS2 (ldi,r31,hlo8(%1)) CR_TAB
- AS2 (mov,%C0,r31) CR_TAB
- AS2 (ldi,r31,hhi8(%1)) CR_TAB
- AS2 (mov,%D0,r31) CR_TAB
- AS2 (mov,r31,__tmp_reg__));
- }
+ return output_reload_insisf (operands, NULL_RTX, real_l);
+ }
else if (GET_CODE (src) == MEM)
return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
}
@@ -3167,6 +3752,12 @@ avr_out_movpsi (rtx insn, rtx *op, int *plen)
rtx dest = op[0];
rtx src = op[1];
+ if (avr_mem_pgm_p (src)
+ || avr_mem_pgm_p (dest))
+ {
+ return avr_out_lpm (insn, op, plen);
+ }
+
if (register_operand (dest, VOIDmode))
{
if (register_operand (src, VOIDmode)) /* mov r,r */
@@ -3192,41 +3783,21 @@ avr_out_movpsi (rtx insn, rtx *op, int *plen)
return avr_asm_len ("mov %C0,%C1", op, plen, 1);
}
}
- else if (CONST_INT_P (src))
- {
- return avr_out_reload_inpsi (op, NULL_RTX, plen);
- }
else if (CONSTANT_P (src))
{
- if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
- {
- return avr_asm_len ("ldi %A0,lo8(%1)" CR_TAB
- "ldi %B0,hi8(%1)" CR_TAB
- "ldi %C0,hh8(%1)", op, plen, -3);
- }
-
- /* Last resort, better than loading from memory. */
- return avr_asm_len ("mov __tmp_reg__,r31" CR_TAB
- "ldi r31,lo8(%1)" CR_TAB
- "mov %A0,r31" CR_TAB
- "ldi r31,hi8(%1)" CR_TAB
- "mov %B0,r31" CR_TAB
- "ldi r31,hh8(%1)" CR_TAB
- "mov %C0,r31" CR_TAB
- "mov r31,__tmp_reg__", op, plen, -8);
+ return avr_out_reload_inpsi (op, NULL_RTX, plen);
}
else if (MEM_P (src))
return avr_out_load_psi (insn, op, plen); /* mov r,m */
}
else if (MEM_P (dest))
{
- if (src == CONST0_RTX (GET_MODE (dest)))
- op[1] = zero_reg_rtx;
-
- avr_out_store_psi (insn, op, plen);
+ rtx xop[2];
+
+ xop[0] = dest;
+ xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
- op[1] = src;
- return "";
+ return avr_out_store_psi (insn, xop, plen);
}
fatal_insn ("invalid insn:", insn);
@@ -3234,88 +3805,71 @@ avr_out_movpsi (rtx insn, rtx *op, int *plen)
}
-const char *
-out_movqi_mr_r (rtx insn, rtx op[], int *l)
+static const char*
+out_movqi_mr_r (rtx insn, rtx op[], int *plen)
{
rtx dest = op[0];
rtx src = op[1];
rtx x = XEXP (dest, 0);
- int dummy;
-
- if (!l)
- l = &dummy;
if (CONSTANT_ADDRESS_P (x))
{
- if (CONST_INT_P (x) && INTVAL (x) == SREG_ADDR)
- {
- *l = 1;
- return AS2 (out,__SREG__,%1);
- }
- if (optimize > 0 && io_address_operand (x, QImode))
- {
- *l = 1;
- return AS2 (out,%m0-0x20,%1);
- }
- *l = 2;
- return AS2 (sts,%m0,%1);
+ return optimize > 0 && io_address_operand (x, QImode)
+ ? avr_asm_len ("out %i0,%1", op, plen, -1)
+ : avr_asm_len ("sts %m0,%1", op, plen, -2);
}
- /* memory access by reg+disp */
- else if (GET_CODE (x) == PLUS
- && REG_P (XEXP (x,0))
- && GET_CODE (XEXP (x,1)) == CONST_INT)
+ else if (GET_CODE (x) == PLUS
+ && REG_P (XEXP (x, 0))
+ && CONST_INT_P (XEXP (x, 1)))
{
- if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (dest))) >= 63)
- {
- int disp = INTVAL (XEXP (x,1));
- if (REGNO (XEXP (x,0)) != REG_Y)
- fatal_insn ("incorrect insn:",insn);
+ /* memory access by reg+disp */
- if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
- return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
- AS2 (std,Y+63,%1) CR_TAB
- AS2 (sbiw,r28,%o0-63));
+ int disp = INTVAL (XEXP (x, 1));
- return *l = 5, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
- AS2 (sbci,r29,hi8(-%o0)) CR_TAB
- AS2 (st,Y,%1) CR_TAB
- AS2 (subi,r28,lo8(%o0)) CR_TAB
- AS2 (sbci,r29,hi8(%o0)));
- }
+ if (disp - GET_MODE_SIZE (GET_MODE (dest)) >= 63)
+ {
+ if (REGNO (XEXP (x, 0)) != REG_Y)
+ fatal_insn ("incorrect insn:",insn);
+
+ if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
+ return avr_asm_len ("adiw r28,%o0-63" CR_TAB
+ "std Y+63,%1" CR_TAB
+ "sbiw r28,%o0-63", op, plen, -3);
+
+ return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
+ "sbci r29,hi8(-%o0)" CR_TAB
+ "st Y,%1" CR_TAB
+ "subi r28,lo8(%o0)" CR_TAB
+ "sbci r29,hi8(%o0)", op, plen, -5);
+ }
else if (REGNO (XEXP (x,0)) == REG_X)
- {
- if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
- {
- if (reg_unused_after (insn, XEXP (x,0)))
- return *l = 3, (AS2 (mov,__tmp_reg__,%1) CR_TAB
- AS2 (adiw,r26,%o0) CR_TAB
- AS2 (st,X,__tmp_reg__));
-
- return *l = 4, (AS2 (mov,__tmp_reg__,%1) CR_TAB
- AS2 (adiw,r26,%o0) CR_TAB
- AS2 (st,X,__tmp_reg__) CR_TAB
- AS2 (sbiw,r26,%o0));
- }
- else
- {
- if (reg_unused_after (insn, XEXP (x,0)))
- return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
- AS2 (st,X,%1));
+ {
+ if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
+ {
+ avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
+ "adiw r26,%o0" CR_TAB
+ "st X,__tmp_reg__", op, plen, -3);
+ }
+ else
+ {
+ avr_asm_len ("adiw r26,%o0" CR_TAB
+ "st X,%1", op, plen, -2);
+ }
+
+ if (!reg_unused_after (insn, XEXP (x,0)))
+ avr_asm_len ("sbiw r26,%o0", op, plen, 1);
- return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
- AS2 (st,X,%1) CR_TAB
- AS2 (sbiw,r26,%o0));
- }
- }
- *l = 1;
- return AS2 (std,%0,%1);
+ return "";
+ }
+
+ return avr_asm_len ("std %0,%1", op, plen, 1);
}
- *l = 1;
- return AS2 (st,%0,%1);
+
+ return avr_asm_len ("st %0,%1", op, plen, 1);
}
-const char *
-out_movhi_mr_r (rtx insn, rtx op[], int *l)
+static const char*
+out_movhi_mr_r (rtx insn, rtx op[], int *plen)
{
rtx dest = op[0];
rtx src = op[1];
@@ -3325,127 +3879,103 @@ out_movhi_mr_r (rtx insn, rtx op[], int *l)
/* "volatile" forces writing high byte first, even if less efficient,
for correct operation with 16-bit I/O registers. */
int mem_volatile_p = MEM_VOLATILE_P (dest);
- int tmp;
- if (!l)
- l = &tmp;
if (CONSTANT_ADDRESS_P (base))
- {
- if (optimize > 0 && io_address_operand (base, HImode))
- {
- *l = 2;
- return (AS2 (out,%m0+1-0x20,%B1) CR_TAB
- AS2 (out,%m0-0x20,%A1));
- }
- return *l = 4, (AS2 (sts,%m0+1,%B1) CR_TAB
- AS2 (sts,%m0,%A1));
- }
+ return optimize > 0 && io_address_operand (base, HImode)
+ ? avr_asm_len ("out %i0+1,%B1" CR_TAB
+ "out %i0,%A1", op, plen, -2)
+
+ : avr_asm_len ("sts %m0+1,%B1" CR_TAB
+ "sts %m0,%A1", op, plen, -4);
+
if (reg_base > 0)
{
- if (reg_base == REG_X)
- {
- if (reg_src == REG_X)
- {
- /* "st X+,r26" and "st -X,r26" are undefined. */
- if (!mem_volatile_p && reg_unused_after (insn, src))
- return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
- AS2 (st,X,r26) CR_TAB
- AS2 (adiw,r26,1) CR_TAB
- AS2 (st,X,__tmp_reg__));
- else
- return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
- AS2 (adiw,r26,1) CR_TAB
- AS2 (st,X,__tmp_reg__) CR_TAB
- AS2 (sbiw,r26,1) CR_TAB
- AS2 (st,X,r26));
- }
- else
- {
- if (!mem_volatile_p && reg_unused_after (insn, base))
- return *l=2, (AS2 (st,X+,%A1) CR_TAB
- AS2 (st,X,%B1));
- else
- return *l=3, (AS2 (adiw,r26,1) CR_TAB
- AS2 (st,X,%B1) CR_TAB
- AS2 (st,-X,%A1));
- }
- }
- else
- return *l=2, (AS2 (std,%0+1,%B1) CR_TAB
- AS2 (st,%0,%A1));
+ if (reg_base != REG_X)
+ return avr_asm_len ("std %0+1,%B1" CR_TAB
+ "st %0,%A1", op, plen, -2);
+
+ if (reg_src == REG_X)
+ /* "st X+,r26" and "st -X,r26" are undefined. */
+ return !mem_volatile_p && reg_unused_after (insn, src)
+ ? avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
+ "st X,r26" CR_TAB
+ "adiw r26,1" CR_TAB
+ "st X,__tmp_reg__", op, plen, -4)
+
+ : avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
+ "adiw r26,1" CR_TAB
+ "st X,__tmp_reg__" CR_TAB
+ "sbiw r26,1" CR_TAB
+ "st X,r26", op, plen, -5);
+
+ return !mem_volatile_p && reg_unused_after (insn, base)
+ ? avr_asm_len ("st X+,%A1" CR_TAB
+ "st X,%B1", op, plen, -2)
+ : avr_asm_len ("adiw r26,1" CR_TAB
+ "st X,%B1" CR_TAB
+ "st -X,%A1", op, plen, -3);
}
else if (GET_CODE (base) == PLUS)
{
int disp = INTVAL (XEXP (base, 1));
reg_base = REGNO (XEXP (base, 0));
if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
- {
- if (reg_base != REG_Y)
- fatal_insn ("incorrect insn:",insn);
-
- if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
- return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
- AS2 (std,Y+63,%B1) CR_TAB
- AS2 (std,Y+62,%A1) CR_TAB
- AS2 (sbiw,r28,%o0-62));
-
- return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
- AS2 (sbci,r29,hi8(-%o0)) CR_TAB
- AS2 (std,Y+1,%B1) CR_TAB
- AS2 (st,Y,%A1) CR_TAB
- AS2 (subi,r28,lo8(%o0)) CR_TAB
- AS2 (sbci,r29,hi8(%o0)));
- }
- if (reg_base == REG_X)
- {
- /* (X + d) = R */
- if (reg_src == REG_X)
- {
- *l = 7;
- return (AS2 (mov,__tmp_reg__,r26) CR_TAB
- AS2 (mov,__zero_reg__,r27) CR_TAB
- AS2 (adiw,r26,%o0+1) CR_TAB
- AS2 (st,X,__zero_reg__) CR_TAB
- AS2 (st,-X,__tmp_reg__) CR_TAB
- AS1 (clr,__zero_reg__) CR_TAB
- AS2 (sbiw,r26,%o0));
- }
- *l = 4;
- return (AS2 (adiw,r26,%o0+1) CR_TAB
- AS2 (st,X,%B1) CR_TAB
- AS2 (st,-X,%A1) CR_TAB
- AS2 (sbiw,r26,%o0));
- }
- return *l=2, (AS2 (std,%B0,%B1) CR_TAB
- AS2 (std,%A0,%A1));
+ {
+ if (reg_base != REG_Y)
+ fatal_insn ("incorrect insn:",insn);
+
+ return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
+ ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
+ "std Y+63,%B1" CR_TAB
+ "std Y+62,%A1" CR_TAB
+ "sbiw r28,%o0-62", op, plen, -4)
+
+ : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
+ "sbci r29,hi8(-%o0)" CR_TAB
+ "std Y+1,%B1" CR_TAB
+ "st Y,%A1" CR_TAB
+ "subi r28,lo8(%o0)" CR_TAB
+ "sbci r29,hi8(%o0)", op, plen, -6);
+ }
+
+ if (reg_base != REG_X)
+ return avr_asm_len ("std %B0,%B1" CR_TAB
+ "std %A0,%A1", op, plen, -2);
+ /* (X + d) = R */
+ return reg_src == REG_X
+ ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
+ "mov __zero_reg__,r27" CR_TAB
+ "adiw r26,%o0+1" CR_TAB
+ "st X,__zero_reg__" CR_TAB
+ "st -X,__tmp_reg__" CR_TAB
+ "clr __zero_reg__" CR_TAB
+ "sbiw r26,%o0", op, plen, -7)
+
+ : avr_asm_len ("adiw r26,%o0+1" CR_TAB
+ "st X,%B1" CR_TAB
+ "st -X,%A1" CR_TAB
+ "sbiw r26,%o0", op, plen, -4);
}
else if (GET_CODE (base) == PRE_DEC) /* (--R) */
- return *l=2, (AS2 (st,%0,%B1) CR_TAB
- AS2 (st,%0,%A1));
+ {
+ return avr_asm_len ("st %0,%B1" CR_TAB
+ "st %0,%A1", op, plen, -2);
+ }
else if (GET_CODE (base) == POST_INC) /* (R++) */
{
- if (mem_volatile_p)
- {
- if (REGNO (XEXP (base, 0)) == REG_X)
- {
- *l = 4;
- return (AS2 (adiw,r26,1) CR_TAB
- AS2 (st,X,%B1) CR_TAB
- AS2 (st,-X,%A1) CR_TAB
- AS2 (adiw,r26,2));
- }
- else
- {
- *l = 3;
- return (AS2 (std,%p0+1,%B1) CR_TAB
- AS2 (st,%p0,%A1) CR_TAB
- AS2 (adiw,%r0,2));
- }
- }
+ if (!mem_volatile_p)
+ return avr_asm_len ("st %0,%A1" CR_TAB
+ "st %0,%B1", op, plen, -2);
+
+ return REGNO (XEXP (base, 0)) == REG_X
+ ? avr_asm_len ("adiw r26,1" CR_TAB
+ "st X,%B1" CR_TAB
+ "st -X,%A1" CR_TAB
+ "adiw r26,2", op, plen, -4)
- *l = 2;
- return (AS2 (st,%0,%A1) CR_TAB
- AS2 (st,%0,%B1));
+ : avr_asm_len ("std %p0+1,%B1" CR_TAB
+ "st %p0,%A1" CR_TAB
+ "adiw %r0,2", op, plen, -3);
}
fatal_insn ("unknown move insn:",insn);
return "";
@@ -3740,150 +4270,126 @@ avr_out_tstsi (rtx insn, rtx *op, int *plen)
}
-/* Generate asm equivalent for various shifts.
- Shift count is a CONST_INT, MEM or REG.
- This only handles cases that are not already
- carefully hand-optimized in ?sh??i3_out. */
+/* Generate asm equivalent for various shifts. This only handles cases
+ that are not already carefully hand-optimized in ?sh??i3_out.
+
+ OPERANDS[0] resp. %0 in TEMPL is the operand to be shifted.
+ OPERANDS[2] is the shift count as CONST_INT, MEM or REG.
+ OPERANDS[3] is a QImode scratch register from LD regs if
+ available and SCRATCH, otherwise (no scratch available)
+
+ TEMPL is an assembler template that shifts by one position.
+ T_LEN is the length of this template. */
void
out_shift_with_cnt (const char *templ, rtx insn, rtx operands[],
- int *len, int t_len)
+ int *plen, int t_len)
{
- rtx op[10];
- char str[500];
- int second_label = 1;
- int saved_in_tmp = 0;
- int use_zero_reg = 0;
+ bool second_label = true;
+ bool saved_in_tmp = false;
+ bool use_zero_reg = false;
+ rtx op[5];
op[0] = operands[0];
op[1] = operands[1];
op[2] = operands[2];
op[3] = operands[3];
- str[0] = 0;
- if (len)
- *len = 1;
+ if (plen)
+ *plen = 0;
- if (GET_CODE (operands[2]) == CONST_INT)
+ if (CONST_INT_P (operands[2]))
{
- int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
+ bool scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
+ && REG_P (operands[3]));
int count = INTVAL (operands[2]);
int max_len = 10; /* If larger than this, always use a loop. */
if (count <= 0)
- {
- if (len)
- *len = 0;
- return;
- }
+ return;
if (count < 8 && !scratch)
- use_zero_reg = 1;
+ use_zero_reg = true;
if (optimize_size)
- max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
+ max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
if (t_len * count <= max_len)
- {
- /* Output shifts inline with no loop - faster. */
- if (len)
- *len = t_len * count;
- else
- {
- while (count-- > 0)
- output_asm_insn (templ, op);
- }
+ {
+ /* Output shifts inline with no loop - faster. */
+
+ while (count-- > 0)
+ avr_asm_len (templ, op, plen, t_len);
- return;
- }
+ return;
+ }
if (scratch)
- {
- if (!len)
- strcat (str, AS2 (ldi,%3,%2));
- }
+ {
+ avr_asm_len ("ldi %3,%2", op, plen, 1);
+ }
else if (use_zero_reg)
- {
- /* Hack to save one word: use __zero_reg__ as loop counter.
- Set one bit, then shift in a loop until it is 0 again. */
+ {
+ /* Hack to save one word: use __zero_reg__ as loop counter.
+ Set one bit, then shift in a loop until it is 0 again. */
- op[3] = zero_reg_rtx;
- if (len)
- *len = 2;
- else
- strcat (str, ("set" CR_TAB
- AS2 (bld,%3,%2-1)));
- }
+ op[3] = zero_reg_rtx;
+
+ avr_asm_len ("set" CR_TAB
+ "bld %3,%2-1", op, plen, 2);
+ }
else
- {
- /* No scratch register available, use one from LD_REGS (saved in
- __tmp_reg__) that doesn't overlap with registers to shift. */
+ {
+ /* No scratch register available, use one from LD_REGS (saved in
+ __tmp_reg__) that doesn't overlap with registers to shift. */
- op[3] = gen_rtx_REG (QImode,
- ((true_regnum (operands[0]) - 1) & 15) + 16);
- op[4] = tmp_reg_rtx;
- saved_in_tmp = 1;
+ op[3] = all_regs_rtx[((REGNO (op[0]) - 1) & 15) + 16];
+ op[4] = tmp_reg_rtx;
+ saved_in_tmp = true;
- if (len)
- *len = 3; /* Includes "mov %3,%4" after the loop. */
- else
- strcat (str, (AS2 (mov,%4,%3) CR_TAB
- AS2 (ldi,%3,%2)));
- }
+ avr_asm_len ("mov %4,%3" CR_TAB
+ "ldi %3,%2", op, plen, 2);
+ }
- second_label = 0;
+ second_label = false;
}
- else if (GET_CODE (operands[2]) == MEM)
+ else if (MEM_P (op[2]))
{
- rtx op_mov[10];
+ rtx op_mov[2];
- op[3] = op_mov[0] = tmp_reg_rtx;
+ op_mov[0] = op[3] = tmp_reg_rtx;
op_mov[1] = op[2];
- if (len)
- out_movqi_r_mr (insn, op_mov, len);
- else
- output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
+ out_movqi_r_mr (insn, op_mov, plen);
}
- else if (register_operand (operands[2], QImode))
+ else if (register_operand (op[2], QImode))
{
- if (reg_unused_after (insn, operands[2])
- && !reg_overlap_mentioned_p (operands[0], operands[2]))
+ op[3] = op[2];
+
+ if (!reg_unused_after (insn, op[2])
+ || reg_overlap_mentioned_p (op[0], op[2]))
{
- op[3] = op[2];
+ op[3] = tmp_reg_rtx;
+ avr_asm_len ("mov %3,%2", op, plen, 1);
}
- else
- {
- op[3] = tmp_reg_rtx;
- if (!len)
- strcat (str, (AS2 (mov,%3,%2) CR_TAB));
- }
}
else
fatal_insn ("bad shift insn:", insn);
if (second_label)
- {
- if (len)
- ++*len;
- else
- strcat (str, AS1 (rjmp,2f));
- }
+ avr_asm_len ("rjmp 2f", op, plen, 1);
- if (len)
- *len += t_len + 2; /* template + dec + brXX */
- else
- {
- strcat (str, "\n1:\t");
- strcat (str, templ);
- strcat (str, second_label ? "\n2:\t" : "\n\t");
- strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
- strcat (str, CR_TAB);
- strcat (str, second_label ? AS1 (brpl,1b) : AS1 (brne,1b));
- if (saved_in_tmp)
- strcat (str, (CR_TAB AS2 (mov,%3,%4)));
- output_asm_insn (str, op);
- }
+ avr_asm_len ("1:", op, plen, 0);
+ avr_asm_len (templ, op, plen, t_len);
+
+ if (second_label)
+ avr_asm_len ("2:", op, plen, 0);
+
+ avr_asm_len (use_zero_reg ? "lsr %3" : "dec %3", op, plen, 1);
+ avr_asm_len (second_label ? "brpl 1b" : "brne 1b", op, plen, 1);
+
+ if (saved_in_tmp)
+ avr_asm_len ("mov %3,%4", op, plen, 1);
}
@@ -5348,7 +5854,7 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc)
bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
op[0] = reg8;
- op[1] = GEN_INT (val8);
+ op[1] = gen_int_mode (val8, QImode);
/* To get usable cc0 no low-bytes must have been skipped. */
@@ -5897,7 +6403,9 @@ adjust_insn_length (rtx insn, int len)
case ADJUST_LEN_MOV16: output_movhi (insn, op, &len); break;
case ADJUST_LEN_MOV24: avr_out_movpsi (insn, op, &len); break;
case ADJUST_LEN_MOV32: output_movsisf (insn, op, &len); break;
-
+ case ADJUST_LEN_MOVMEM: avr_out_movmem (insn, op, &len); break;
+ case ADJUST_LEN_XLOAD: avr_out_xload (insn, op, &len); break;
+
case ADJUST_LEN_TSTHI: avr_out_tsthi (insn, op, &len); break;
case ADJUST_LEN_TSTPSI: avr_out_tstpsi (insn, op, &len); break;
case ADJUST_LEN_TSTSI: avr_out_tstsi (insn, op, &len); break;
@@ -5921,6 +6429,8 @@ adjust_insn_length (rtx insn, int len)
case ADJUST_LEN_CALL: len = AVR_HAVE_JMP_CALL ? 2 : 1; break;
+ case ADJUST_LEN_MAP_BITS: avr_out_map_bits (insn, op, &len); break;
+
default:
gcc_unreachable();
}
@@ -6042,6 +6552,49 @@ _reg_unused_after (rtx insn, rtx reg)
return 1;
}
+
+/* Return RTX that represents the lower 16 bits of a constant address.
+ Unfortunately, simplify_gen_subreg does not handle this case. */
+
+static rtx
+avr_const_address_lo16 (rtx x)
+{
+ rtx lo16;
+
+ switch (GET_CODE (x))
+ {
+ default:
+ break;
+
+ case CONST:
+ if (PLUS == GET_CODE (XEXP (x, 0))
+ && SYMBOL_REF == GET_CODE (XEXP (XEXP (x, 0), 0))
+ && CONST_INT_P (XEXP (XEXP (x, 0), 1)))
+ {
+ HOST_WIDE_INT offset = INTVAL (XEXP (XEXP (x, 0), 1));
+ const char *name = XSTR (XEXP (XEXP (x, 0), 0), 0);
+
+ lo16 = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
+ lo16 = gen_rtx_CONST (Pmode, plus_constant (lo16, offset));
+
+ return lo16;
+ }
+
+ break;
+
+ case SYMBOL_REF:
+ {
+ const char *name = XSTR (x, 0);
+
+ return gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
+ }
+ }
+
+ avr_edump ("\n%?: %r\n", x);
+ gcc_unreachable();
+}
+
+
/* Target hook for assembling integer objects. The AVR version needs
special handling for references to certain labels. */
@@ -6054,11 +6607,30 @@ avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
fputs ("\t.word\tgs(", asm_out_file);
output_addr_const (asm_out_file, x);
fputs (")\n", asm_out_file);
+
+ return true;
+ }
+ else if (GET_MODE (x) == PSImode)
+ {
+ default_assemble_integer (avr_const_address_lo16 (x),
+ GET_MODE_SIZE (HImode), aligned_p);
+
+ fputs ("\t.warning\t\"assembling 24-bit address needs binutils extension for hh8(",
+ asm_out_file);
+ output_addr_const (asm_out_file, x);
+ fputs (")\"\n", asm_out_file);
+
+ fputs ("\t.byte\t0\t" ASM_COMMENT_START " hh8(", asm_out_file);
+ output_addr_const (asm_out_file, x);
+ fputs (")\n", asm_out_file);
+
return true;
}
+
return default_assemble_integer (x, size, aligned_p);
}
+
/* Worker function for ASM_DECLARE_FUNCTION_NAME. */
void
@@ -6208,8 +6780,16 @@ avr_attribute_table[] =
{ NULL, 0, 0, false, false, false, NULL, false }
};
-/* Look for attribute `progmem' in DECL
- if found return 1, otherwise 0. */
+
+/* Look if DECL shall be placed in program memory space by
+ means of attribute `progmem' or some address-space qualifier.
+ Return non-zero if DECL is data that must end up in Flash and
+ zero if the data lives in RAM (.bss, .data, .rodata, ...).
+
+ Return 2 if DECL is located in 24-bit flash address-space
+ Return 1 if DECL is located in 16-bit flash address-space
+ Return -1 if attribute `progmem' occurs in DECL or ATTRIBUTES
+ Return 0 otherwise */
int
avr_progmem_p (tree decl, tree attributes)
@@ -6219,11 +6799,18 @@ avr_progmem_p (tree decl, tree attributes)
if (TREE_CODE (decl) != VAR_DECL)
return 0;
+ if (avr_decl_pgmx_p (decl))
+ return 2;
+
+ if (avr_decl_pgm_p (decl))
+ return 1;
+
if (NULL_TREE
!= lookup_attribute ("progmem", attributes))
- return 1;
+ return -1;
- a=decl;
+ a = decl;
+
do
a = TREE_TYPE(a);
while (TREE_CODE (a) == ARRAY_TYPE);
@@ -6232,16 +6819,123 @@ avr_progmem_p (tree decl, tree attributes)
return 0;
if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
- return 1;
+ return -1;
return 0;
}
+
+/* Scan type TYP for pointer references to address space ASn.
+ Return ADDR_SPACE_GENERIC (i.e. 0) if all pointers targeting
+ the AS are also declared to be CONST.
+ Otherwise, return the respective addres space, i.e. a value != 0. */
+
+static addr_space_t
+avr_nonconst_pointer_addrspace (tree typ)
+{
+ while (ARRAY_TYPE == TREE_CODE (typ))
+ typ = TREE_TYPE (typ);
+
+ if (POINTER_TYPE_P (typ))
+ {
+ tree target = TREE_TYPE (typ);
+
+ /* Pointer to function: Test the function's return type. */
+
+ if (FUNCTION_TYPE == TREE_CODE (target))
+ return avr_nonconst_pointer_addrspace (TREE_TYPE (target));
+
+ /* "Ordinary" pointers... */
+
+ while (TREE_CODE (target) == ARRAY_TYPE)
+ target = TREE_TYPE (target);
+
+ if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (target))
+ && !TYPE_READONLY (target))
+ {
+ /* Pointers to non-generic address space must be const. */
+
+ return TYPE_ADDR_SPACE (target);
+ }
+
+ /* Scan pointer's target type. */
+
+ return avr_nonconst_pointer_addrspace (target);
+ }
+
+ return ADDR_SPACE_GENERIC;
+}
+
+
+/* Sanity check NODE so that all pointers targeting address space AS1
+ go along with CONST qualifier. Writing to this address space should
+ be detected and complained about as early as possible. */
+
+static bool
+avr_pgm_check_var_decl (tree node)
+{
+ const char *reason = NULL;
+
+ addr_space_t as = ADDR_SPACE_GENERIC;
+
+ gcc_assert (as == 0);
+
+ if (avr_log.progmem)
+ avr_edump ("%?: %t\n", node);
+
+ switch (TREE_CODE (node))
+ {
+ default:
+ break;
+
+ case VAR_DECL:
+ if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
+ reason = "variable";
+ break;
+
+ case PARM_DECL:
+ if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
+ reason = "function parameter";
+ break;
+
+ case FIELD_DECL:
+ if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
+ reason = "structure field";
+ break;
+
+ case FUNCTION_DECL:
+ if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (TREE_TYPE (node))),
+ as)
+ reason = "return type of function";
+ break;
+
+ case POINTER_TYPE:
+ if (as = avr_nonconst_pointer_addrspace (node), as)
+ reason = "pointer";
+ break;
+ }
+
+ if (reason)
+ {
+ if (TYPE_P (node))
+ error ("pointer targeting address space %qs must be const in %qT",
+ c_addr_space_name (as), node);
+ else
+ error ("pointer targeting address space %qs must be const in %s %q+D",
+ c_addr_space_name (as), reason, node);
+ }
+
+ return reason == NULL;
+}
+
+
/* Add the section attribute if the variable is in progmem. */
static void
avr_insert_attributes (tree node, tree *attributes)
{
+ avr_pgm_check_var_decl (node);
+
if (TREE_CODE (node) == VAR_DECL
&& (TREE_STATIC (node) || DECL_EXTERNAL (node))
&& avr_progmem_p (node, *attributes))
@@ -6258,11 +6952,20 @@ avr_insert_attributes (tree node, tree *attributes)
if (error_mark_node == node0)
return;
- if (!TYPE_READONLY (node0))
+ if (!TYPE_READONLY (node0)
+ && !TREE_READONLY (node))
{
+ addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (node));
+ const char *reason = "__attribute__((progmem))";
+
+ if (!ADDR_SPACE_GENERIC_P (as))
+ reason = c_addr_space_name (as);
+
+ if (avr_log.progmem)
+ avr_edump ("\n%?: %t\n%t\n", node, node0);
+
error ("variable %q+D must be const in order to be put into"
- " read-only section by means of %<__attribute__((progmem))%>",
- node);
+ " read-only section by means of %qs", node, reason);
}
}
}
@@ -6314,11 +7017,23 @@ avr_output_bss_section_asm_op (const void *data)
}
+/* Unnamed section callback for progmem*.data sections. */
+
+static void
+avr_output_progmem_section_asm_op (const void *data)
+{
+ fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n",
+ (const char*) data);
+}
+
+
/* Implement `TARGET_ASM_INIT_SECTIONS'. */
static void
avr_asm_init_sections (void)
{
+ unsigned int n;
+
/* Set up a section for jump tables. Alignment is handled by
ASM_OUTPUT_BEFORE_CASE_LABEL. */
@@ -6337,9 +7052,12 @@ avr_asm_init_sections (void)
",\"ax\",@progbits");
}
- progmem_section
- = get_unnamed_section (0, output_section_asm_op,
- "\t.section\t.progmem.data,\"a\",@progbits");
+ for (n = 0; n < sizeof (progmem_section) / sizeof (*progmem_section); n++)
+ {
+ progmem_section[n]
+ = get_unnamed_section (0, avr_output_progmem_section_asm_op,
+ progmem_section_prefix[n]);
+ }
/* Override section callbacks to keep track of `avr_need_clear_bss_p'
resp. `avr_need_copy_data_p'. */
@@ -6418,8 +7136,9 @@ avr_asm_named_section (const char *name, unsigned int flags, tree decl)
{
if (flags & AVR_SECTION_PROGMEM)
{
+ int segment = (flags & AVR_SECTION_PROGMEM) / SECTION_MACH_DEP - 1;
const char *old_prefix = ".rodata";
- const char *new_prefix = ".progmem.data";
+ const char *new_prefix = progmem_section_prefix[segment];
const char *sname = new_prefix;
if (STR_PREFIX_P (name, old_prefix))
@@ -6446,6 +7165,7 @@ avr_asm_named_section (const char *name, unsigned int flags, tree decl)
static unsigned int
avr_section_type_flags (tree decl, const char *name, int reloc)
{
+ int prog;
unsigned int flags = default_section_type_flags (decl, name, reloc);
if (STR_PREFIX_P (name, ".noinit"))
@@ -6459,10 +7179,16 @@ avr_section_type_flags (tree decl, const char *name, int reloc)
}
if (decl && DECL_P (decl)
- && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
+ && (prog = avr_progmem_p (decl, DECL_ATTRIBUTES (decl)), prog))
{
+ int segment = 0;
+
+ if (prog == 1)
+ segment = avr_pgm_segment (TYPE_ADDR_SPACE (TREE_TYPE (decl)));
+
flags &= ~SECTION_WRITE;
- flags |= AVR_SECTION_PROGMEM;
+ flags &= ~SECTION_BSS;
+ flags |= (1 + segment % avr_current_arch->n_segments) * SECTION_MACH_DEP;
}
return flags;
@@ -6498,16 +7224,25 @@ avr_encode_section_info (tree decl, rtx rtl,
static section *
avr_asm_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
{
+ int prog;
+
section * sect = default_elf_select_section (decl, reloc, align);
if (decl && DECL_P (decl)
- && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
+ && (prog = avr_progmem_p (decl, DECL_ATTRIBUTES (decl)), prog))
{
+ int segment = 0;
+
+ if (prog == 1)
+ segment = avr_pgm_segment (TYPE_ADDR_SPACE (TREE_TYPE (decl)));
+
+ segment %= avr_current_arch->n_segments;
+
if (sect->common.flags & SECTION_NAMED)
{
const char * name = sect->named.name;
const char * old_prefix = ".rodata";
- const char * new_prefix = ".progmem.data";
+ const char * new_prefix = progmem_section_prefix[segment];
if (STR_PREFIX_P (name, old_prefix))
{
@@ -6518,31 +7253,38 @@ avr_asm_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
}
}
- return progmem_section;
+ return progmem_section[segment];
}
return sect;
}
/* Implement `TARGET_ASM_FILE_START'. */
-/* Outputs some appropriate text to go at the start of an assembler
- file. */
+/* Outputs some text at the start of each assembler file. */
static void
avr_file_start (void)
{
+ int sfr_offset = avr_current_arch->sfr_offset;
+
if (avr_current_arch->asm_only)
error ("MCU %qs supported for assembler only", avr_current_device->name);
default_file_start ();
-/* fprintf (asm_out_file, "\t.arch %s\n", avr_current_device->name);*/
- fputs ("__SREG__ = 0x3f\n"
- "__SP_H__ = 0x3e\n"
- "__SP_L__ = 0x3d\n", asm_out_file);
-
- fputs ("__tmp_reg__ = 0\n"
- "__zero_reg__ = 1\n", asm_out_file);
+ fprintf (asm_out_file,
+ "__SREG__ = 0x%02x\n"
+ "__SP_H__ = 0x%02x\n"
+ "__SP_L__ = 0x%02x\n"
+ "__RAMPZ__ = 0x%02x\n"
+ "__tmp_reg__ = %d\n"
+ "__zero_reg__ = %d\n",
+ -sfr_offset + SREG_ADDR,
+ -sfr_offset + SP_ADDR + 1,
+ -sfr_offset + SP_ADDR,
+ -sfr_offset + RAMPZ_ADDR,
+ TMP_REGNO,
+ ZERO_REGNO);
}
@@ -8049,10 +8791,14 @@ 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,
- addr_space_t as ATTRIBUTE_UNUSED,
- RTX_CODE outer_code,
+ addr_space_t as, RTX_CODE outer_code,
RTX_CODE index_code ATTRIBUTE_UNUSED)
{
+ if (!ADDR_SPACE_GENERIC_P (as))
+ {
+ return POINTER_Z_REGS;
+ }
+
if (!avr_strict_X)
return reload_completed ? BASE_POINTER_REGS : POINTER_REGS;
@@ -8071,6 +8817,27 @@ avr_regno_mode_code_ok_for_base_p (int regno,
{
bool ok = false;
+ if (!ADDR_SPACE_GENERIC_P (as))
+ {
+ if (regno < FIRST_PSEUDO_REGISTER
+ && regno == REG_Z)
+ {
+ return true;
+ }
+
+ if (reg_renumber)
+ {
+ regno = reg_renumber[regno];
+
+ if (regno == REG_Z)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
if (regno < FIRST_PSEUDO_REGISTER
&& (regno == REG_X
|| regno == REG_Y
@@ -8110,7 +8877,13 @@ avr_regno_mode_code_ok_for_base_p (int regno,
LEN != NULL: set *LEN to the length of the instruction sequence
(in words) printed with LEN = NULL.
If CLEAR_P is true, OP[0] had been cleard to Zero already.
- If CLEAR_P is false, nothing is known about OP[0]. */
+ If CLEAR_P is false, nothing is known about OP[0].
+
+ The effect on cc0 is as follows:
+
+ Load 0 to any register : NONE
+ Load ld register with any value : NONE
+ Anything else: : CLOBBER */
static void
output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
@@ -8122,9 +8895,8 @@ output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
int clobber_val = 1234;
bool cooked_clobber_p = false;
bool set_p = false;
- unsigned int n;
enum machine_mode mode = GET_MODE (dest);
- int n_bytes = GET_MODE_SIZE (mode);
+ int n, n_bytes = GET_MODE_SIZE (mode);
gcc_assert (REG_P (dest)
&& CONSTANT_P (src));
@@ -8138,7 +8910,7 @@ output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
if (REGNO (dest) < 16
&& REGNO (dest) + GET_MODE_SIZE (mode) > 16)
{
- clobber_reg = gen_rtx_REG (QImode, REGNO (dest) + n_bytes - 1);
+ clobber_reg = all_regs_rtx[REGNO (dest) + n_bytes - 1];
}
/* We might need a clobber reg but don't have one. Look at the value to
@@ -8155,7 +8927,7 @@ output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
That's cheaper than loading from constant pool. */
cooked_clobber_p = true;
- clobber_reg = gen_rtx_REG (QImode, REG_Z + 1);
+ clobber_reg = all_regs_rtx[REG_Z + 1];
avr_asm_len ("mov __tmp_reg__,%0", &clobber_reg, len, 1);
}
@@ -8165,7 +8937,7 @@ output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
{
int ldreg_p;
bool done_byte = false;
- unsigned int j;
+ int j;
rtx xop[3];
/* Crop the n-th destination byte. */
@@ -8188,8 +8960,8 @@ output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
xop[1] = src;
xop[2] = clobber_reg;
- if (n >= 2)
- avr_asm_len ("clr %0", xop, len, 1);
+ if (n >= 2 + (avr_current_arch->n_segments > 1))
+ avr_asm_len ("mov %0,__zero_reg__", xop, len, 1);
else
avr_asm_len (asm_code[n][ldreg_p], xop, len, ldreg_p ? 1 : 2);
continue;
@@ -8221,14 +8993,13 @@ output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
}
}
- /* Use CLR to zero a value so that cc0 is set as expected
- for zero. */
+ /* Don't use CLR so that cc0 is set as expected. */
if (ival[n] == 0)
{
if (!clear_p)
- avr_asm_len ("clr %0", &xdest[n], len, 1);
-
+ avr_asm_len (ldreg_p ? "ldi %0,0" : "mov %0,__zero_reg__",
+ &xdest[n], len, 1);
continue;
}
@@ -8364,7 +9135,9 @@ const char *
output_reload_insisf (rtx *op, rtx clobber_reg, int *len)
{
if (AVR_HAVE_MOVW
- && !test_hard_reg_class (LD_REGS, op[0]))
+ && !test_hard_reg_class (LD_REGS, op[0])
+ && (CONST_INT_P (op[1])
+ || CONST_DOUBLE_P (op[1])))
{
int len_clr, len_noclr;
@@ -8498,8 +9271,8 @@ const char *
avr_out_sbxx_branch (rtx insn, rtx operands[])
{
enum rtx_code comp = GET_CODE (operands[0]);
- int long_jump = (get_attr_length (insn) >= 4);
- int reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
+ bool long_jump = get_attr_length (insn) >= 4;
+ bool reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
if (comp == GE)
comp = EQ;
@@ -8509,49 +9282,61 @@ avr_out_sbxx_branch (rtx insn, rtx operands[])
if (reverse)
comp = reverse_condition (comp);
- if (GET_CODE (operands[1]) == CONST_INT)
+ switch (GET_CODE (operands[1]))
{
- if (INTVAL (operands[1]) < 0x40)
- {
- if (comp == EQ)
- output_asm_insn (AS2 (sbis,%m1-0x20,%2), operands);
- else
- output_asm_insn (AS2 (sbic,%m1-0x20,%2), operands);
- }
+ default:
+ gcc_unreachable();
+
+ case CONST_INT:
+
+ if (low_io_address_operand (operands[1], QImode))
+ {
+ if (comp == EQ)
+ output_asm_insn ("sbis %i1,%2", operands);
+ else
+ output_asm_insn ("sbic %i1,%2", operands);
+ }
else
- {
- output_asm_insn (AS2 (in,__tmp_reg__,%m1-0x20), operands);
- if (comp == EQ)
- output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
- else
- output_asm_insn (AS2 (sbrc,__tmp_reg__,%2), operands);
- }
- }
- else /* GET_CODE (operands[1]) == REG */
- {
+ {
+ output_asm_insn ("in __tmp_reg__,%i1", operands);
+ if (comp == EQ)
+ output_asm_insn ("sbrs __tmp_reg__,%2", operands);
+ else
+ output_asm_insn ("sbrc __tmp_reg__,%2", operands);
+ }
+
+ break; /* CONST_INT */
+
+ case REG:
+
if (GET_MODE (operands[1]) == QImode)
- {
- if (comp == EQ)
- output_asm_insn (AS2 (sbrs,%1,%2), operands);
- else
- output_asm_insn (AS2 (sbrc,%1,%2), operands);
- }
- else /* HImode or SImode */
- {
- static char buf[] = "sbrc %A1,0";
- int bit_nr = INTVAL (operands[2]);
- buf[3] = (comp == EQ) ? 's' : 'c';
- buf[6] = 'A' + (bit_nr >> 3);
- buf[9] = '0' + (bit_nr & 7);
- output_asm_insn (buf, operands);
- }
- }
+ {
+ if (comp == EQ)
+ output_asm_insn ("sbrs %1,%2", operands);
+ else
+ output_asm_insn ("sbrc %1,%2", operands);
+ }
+ else /* HImode, PSImode or SImode */
+ {
+ static char buf[] = "sbrc %A1,0";
+ unsigned int bit_nr = UINTVAL (operands[2]);
+
+ buf[3] = (comp == EQ) ? 's' : 'c';
+ buf[6] = 'A' + (bit_nr / 8);
+ buf[9] = '0' + (bit_nr % 8);
+ output_asm_insn (buf, operands);
+ }
+
+ break; /* REG */
+ } /* switch */
if (long_jump)
- return (AS1 (rjmp,.+4) CR_TAB
- AS1 (jmp,%x3));
+ return ("rjmp .+4" CR_TAB
+ "jmp %x3");
+
if (!reverse)
- return AS1 (rjmp,%x3);
+ return "rjmp %x3";
+
return "";
}
@@ -8595,6 +9380,451 @@ avr_case_values_threshold (void)
return (!AVR_HAVE_JMP_CALL || TARGET_CALL_PROLOGUES) ? 8 : 17;
}
+
+/* Implement `TARGET_ADDR_SPACE_ADDRESS_MODE'. */
+
+static enum machine_mode
+avr_addr_space_address_mode (addr_space_t as)
+{
+ return as == ADDR_SPACE_PGMX ? PSImode : HImode;
+}
+
+
+/* Implement `TARGET_ADDR_SPACE_POINTER_MODE'. */
+
+static enum machine_mode
+avr_addr_space_pointer_mode (addr_space_t as)
+{
+ return as == ADDR_SPACE_PGMX ? PSImode : HImode;
+}
+
+
+/* Helper for following function. */
+
+static bool
+avr_reg_ok_for_pgm_addr (rtx reg, bool strict)
+{
+ gcc_assert (REG_P (reg));
+
+ if (strict)
+ {
+ return REGNO (reg) == REG_Z;
+ }
+
+ /* Avoid combine to propagate hard regs. */
+
+ if (can_create_pseudo_p()
+ && REGNO (reg) < REG_Z)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+
+/* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'. */
+
+static bool
+avr_addr_space_legitimate_address_p (enum machine_mode mode, rtx x,
+ bool strict, addr_space_t as)
+{
+ bool ok = false;
+
+ switch (as)
+ {
+ default:
+ gcc_unreachable();
+
+ case ADDR_SPACE_GENERIC:
+ return avr_legitimate_address_p (mode, x, strict);
+
+ case ADDR_SPACE_PGM:
+ case ADDR_SPACE_PGM1:
+ case ADDR_SPACE_PGM2:
+ case ADDR_SPACE_PGM3:
+ case ADDR_SPACE_PGM4:
+ case ADDR_SPACE_PGM5:
+
+ switch (GET_CODE (x))
+ {
+ case REG:
+ ok = avr_reg_ok_for_pgm_addr (x, strict);
+ break;
+
+ case POST_INC:
+ ok = avr_reg_ok_for_pgm_addr (XEXP (x, 0), strict);
+ break;
+
+ default:
+ break;
+ }
+
+ break; /* PGM */
+
+ case ADDR_SPACE_PGMX:
+ if (REG_P (x))
+ ok = (!strict
+ && can_create_pseudo_p());
+
+ if (LO_SUM == GET_CODE (x))
+ {
+ rtx hi = XEXP (x, 0);
+ rtx lo = XEXP (x, 1);
+
+ ok = (REG_P (hi)
+ && (!strict || REGNO (hi) < FIRST_PSEUDO_REGISTER)
+ && REG_P (lo)
+ && REGNO (lo) == REG_Z);
+ }
+
+ break; /* PGMX */
+ }
+
+ if (avr_log.legitimate_address_p)
+ {
+ avr_edump ("\n%?: ret=%b, mode=%m strict=%d "
+ "reload_completed=%d reload_in_progress=%d %s:",
+ ok, mode, strict, reload_completed, reload_in_progress,
+ reg_renumber ? "(reg_renumber)" : "");
+
+ if (GET_CODE (x) == PLUS
+ && REG_P (XEXP (x, 0))
+ && CONST_INT_P (XEXP (x, 1))
+ && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
+ && reg_renumber)
+ {
+ avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
+ true_regnum (XEXP (x, 0)));
+ }
+
+ avr_edump ("\n%r\n", x);
+ }
+
+ return ok;
+}
+
+
+/* Implement `TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS'. */
+
+static rtx
+avr_addr_space_legitimize_address (rtx x, rtx old_x,
+ enum machine_mode mode, addr_space_t as)
+{
+ if (ADDR_SPACE_GENERIC_P (as))
+ return avr_legitimize_address (x, old_x, mode);
+
+ if (avr_log.legitimize_address)
+ {
+ avr_edump ("\n%?: mode=%m\n %r\n", mode, old_x);
+ }
+
+ return old_x;
+}
+
+
+/* Implement `TARGET_ADDR_SPACE_CONVERT'. */
+
+static rtx
+avr_addr_space_convert (rtx src, tree type_from, tree type_to)
+{
+ addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (type_from));
+ addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type_to));
+
+ if (avr_log.progmem)
+ avr_edump ("\n%!: op = %r\nfrom = %t\nto = %t\n",
+ src, type_from, type_to);
+
+ if (as_from != ADDR_SPACE_PGMX
+ && as_to == ADDR_SPACE_PGMX)
+ {
+ rtx new_src;
+ int n_segments = avr_current_arch->n_segments;
+ RTX_CODE code = GET_CODE (src);
+
+ if (CONST == code
+ && PLUS == GET_CODE (XEXP (src, 0))
+ && SYMBOL_REF == GET_CODE (XEXP (XEXP (src, 0), 0))
+ && CONST_INT_P (XEXP (XEXP (src, 0), 1)))
+ {
+ HOST_WIDE_INT offset = INTVAL (XEXP (XEXP (src, 0), 1));
+ const char *name = XSTR (XEXP (XEXP (src, 0), 0), 0);
+
+ new_src = gen_rtx_SYMBOL_REF (PSImode, ggc_strdup (name));
+ new_src = gen_rtx_CONST (PSImode,
+ plus_constant (new_src, offset));
+ return new_src;
+ }
+
+ if (SYMBOL_REF == code)
+ {
+ const char *name = XSTR (src, 0);
+
+ return gen_rtx_SYMBOL_REF (PSImode, ggc_strdup (name));
+ }
+
+ src = force_reg (Pmode, src);
+
+ if (ADDR_SPACE_GENERIC_P (as_from)
+ || as_from == ADDR_SPACE_PGM
+ || n_segments == 1)
+ {
+ return gen_rtx_ZERO_EXTEND (PSImode, src);
+ }
+ else
+ {
+ int segment = avr_pgm_segment (as_from) % n_segments;
+
+ new_src = gen_reg_rtx (PSImode);
+ emit_insn (gen_n_extendhipsi2 (new_src, GEN_INT (segment), src));
+
+ return new_src;
+ }
+ }
+
+ return src;
+}
+
+
+/* Implement `TARGET_ADDR_SPACE_SUBSET_P'. */
+
+static bool
+avr_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
+{
+ if (subset == ADDR_SPACE_PGMX
+ && superset != ADDR_SPACE_PGMX)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+
+/* Worker function for movmemhi insn.
+ XOP[0] Destination as MEM:BLK
+ XOP[1] Source " "
+ XOP[2] # Bytes to copy
+
+ Return TRUE if the expansion is accomplished.
+ Return FALSE if the operand compination is not supported. */
+
+bool
+avr_emit_movmemhi (rtx *xop)
+{
+ HOST_WIDE_INT count;
+ enum machine_mode loop_mode;
+ addr_space_t as = MEM_ADDR_SPACE (xop[1]);
+ rtx loop_reg, addr0, addr1, a_src, a_dest, insn, xas, reg_x;
+ rtx a_hi8 = NULL_RTX;
+
+ if (avr_mem_pgm_p (xop[0]))
+ return false;
+
+ if (!CONST_INT_P (xop[2]))
+ return false;
+
+ count = INTVAL (xop[2]);
+ if (count <= 0)
+ return false;
+
+ a_src = XEXP (xop[1], 0);
+ a_dest = XEXP (xop[0], 0);
+
+ /* See if constant fits in 8 bits. */
+
+ loop_mode = (count <= 0x100) ? QImode : HImode;
+
+ if (PSImode == GET_MODE (a_src))
+ {
+ addr1 = simplify_gen_subreg (HImode, a_src, PSImode, 0);
+ a_hi8 = simplify_gen_subreg (QImode, a_src, PSImode, 2);
+ }
+ else
+ {
+ int seg = avr_pgm_segment (as);
+
+ addr1 = a_src;
+
+ if (seg > 0
+ && seg % avr_current_arch->n_segments > 0)
+ {
+ a_hi8 = GEN_INT (seg % avr_current_arch->n_segments);
+ }
+ }
+
+ if (a_hi8
+ && avr_current_arch->n_segments > 1)
+ {
+ emit_move_insn (rampz_rtx, a_hi8 = copy_to_mode_reg (QImode, a_hi8));
+ }
+ else if (!ADDR_SPACE_GENERIC_P (as))
+ {
+ as = ADDR_SPACE_PGM;
+ }
+
+ xas = GEN_INT (as);
+
+ /* Create loop counter register */
+
+ loop_reg = copy_to_mode_reg (loop_mode, gen_int_mode (count, loop_mode));
+
+ /* Copy pointers into new pseudos - they will be changed */
+
+ addr0 = copy_to_mode_reg (HImode, a_dest);
+ addr1 = copy_to_mode_reg (HImode, addr1);
+
+ /* FIXME: Register allocator might come up with spill fails if it is left
+ on its own. Thus, we allocate the pointer registers by hand. */
+
+ emit_move_insn (lpm_addr_reg_rtx, addr1);
+ addr1 = lpm_addr_reg_rtx;
+
+ reg_x = gen_rtx_REG (HImode, REG_X);
+ emit_move_insn (reg_x, addr0);
+ addr0 = reg_x;
+
+ /* FIXME: Register allocator does a bad job and might spill address
+ register(s) inside the loop leading to additional move instruction
+ to/from stack which could clobber tmp_reg. Thus, do *not* emit
+ load and store as seperate insns. Instead, we perform the copy
+ by means of one monolithic insn. */
+
+ if (ADDR_SPACE_GENERIC_P (as))
+ {
+ rtx (*fun) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx)
+ = QImode == loop_mode ? gen_movmem_qi : gen_movmem_hi;
+
+ insn = fun (addr0, addr1, xas, loop_reg,
+ addr0, addr1, tmp_reg_rtx, loop_reg);
+ }
+ else if (as == ADDR_SPACE_PGM)
+ {
+ rtx (*fun) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx)
+ = QImode == loop_mode ? gen_movmem_qi : gen_movmem_hi;
+
+ insn = fun (addr0, addr1, xas, loop_reg, addr0, addr1,
+ AVR_HAVE_LPMX ? tmp_reg_rtx : lpm_reg_rtx, loop_reg);
+ }
+ else
+ {
+ rtx (*fun) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx)
+ = QImode == loop_mode ? gen_movmem_qi_elpm : gen_movmem_hi_elpm;
+
+ insn = fun (addr0, addr1, xas, loop_reg, addr0, addr1,
+ AVR_HAVE_ELPMX ? tmp_reg_rtx : lpm_reg_rtx, loop_reg,
+ a_hi8, a_hi8, GEN_INT (RAMPZ_ADDR));
+ }
+
+ set_mem_addr_space (SET_SRC (XVECEXP (insn, 0, 0)), as);
+ emit_insn (insn);
+
+ return true;
+}
+
+
+/* Print assembler for movmem_qi, movmem_hi insns...
+ $0, $4 : & dest
+ $1, $5 : & src
+ $2 : Address Space
+ $3, $7 : Loop register
+ $6 : Scratch register
+
+ ...and movmem_qi_elpm, movmem_hi_elpm insns.
+
+ $8, $9 : hh8 (& src)
+ $10 : RAMPZ_ADDR
+*/
+
+const char*
+avr_out_movmem (rtx insn ATTRIBUTE_UNUSED, rtx *xop, int *plen)
+{
+ addr_space_t as = (addr_space_t) INTVAL (xop[2]);
+ enum machine_mode loop_mode = GET_MODE (xop[3]);
+
+ bool sbiw_p = test_hard_reg_class (ADDW_REGS, xop[3]);
+
+ gcc_assert (REG_X == REGNO (xop[0])
+ && REG_Z == REGNO (xop[1]));
+
+ if (plen)
+ *plen = 0;
+
+ /* Loop label */
+
+ avr_asm_len ("0:", xop, plen, 0);
+
+ /* Load with post-increment */
+
+ switch (as)
+ {
+ default:
+ gcc_unreachable();
+
+ case ADDR_SPACE_GENERIC:
+
+ avr_asm_len ("ld %6,%a1+", xop, plen, 1);
+ break;
+
+ case ADDR_SPACE_PGM:
+
+ if (AVR_HAVE_LPMX)
+ avr_asm_len ("lpm %6,%a1+", xop, plen, 1);
+ else
+ avr_asm_len ("lpm" CR_TAB
+ "adiw %1,1", xop, plen, 2);
+ break;
+
+ case ADDR_SPACE_PGM1:
+ case ADDR_SPACE_PGM2:
+ case ADDR_SPACE_PGM3:
+ case ADDR_SPACE_PGM4:
+ case ADDR_SPACE_PGM5:
+ case ADDR_SPACE_PGMX:
+
+ if (AVR_HAVE_ELPMX)
+ avr_asm_len ("elpm %6,%a1+", xop, plen, 1);
+ else
+ avr_asm_len ("elpm" CR_TAB
+ "adiw %1,1", xop, plen, 2);
+
+ if (as == ADDR_SPACE_PGMX
+ && !AVR_HAVE_ELPMX)
+ {
+ avr_asm_len ("adc %8,__zero_reg__" CR_TAB
+ "out __RAMPZ__,%8", xop, plen, 2);
+ }
+
+ break;
+ }
+
+ /* Store with post-increment */
+
+ avr_asm_len ("st %a0+,%6", xop, plen, 1);
+
+ /* Decrement loop-counter and set Z-flag */
+
+ if (QImode == loop_mode)
+ {
+ avr_asm_len ("dec %3", xop, plen, 1);
+ }
+ else if (sbiw_p)
+ {
+ avr_asm_len ("sbiw %3,1", xop, plen, 1);
+ }
+ else
+ {
+ avr_asm_len ("subi %A3,1" CR_TAB
+ "sbci %B3,0", xop, plen, 2);
+ }
+
+ /* Loop until zero */
+
+ return avr_asm_len ("brne 0b", xop, plen, 1);
+}
+
+
+
/* Helper for __builtin_avr_delay_cycles */
static void
@@ -8655,6 +9885,345 @@ avr_expand_delay_cycles (rtx operands0)
}
}
+
+/* Return VAL * BASE + DIGIT. BASE = 0 is shortcut for BASE = 2^{32} */
+
+static double_int
+avr_double_int_push_digit (double_int val, int base,
+ unsigned HOST_WIDE_INT digit)
+{
+ val = 0 == base
+ ? double_int_lshift (val, 32, 64, false)
+ : double_int_mul (val, uhwi_to_double_int (base));
+
+ return double_int_add (val, uhwi_to_double_int (digit));
+}
+
+
+/* Compute the image of x under f, i.e. perform x --> f(x) */
+
+static int
+avr_map (double_int f, int x)
+{
+ return 0xf & double_int_to_uhwi (double_int_rshift (f, 4*x, 64, false));
+}
+
+
+/* Return the map R that reverses the bits of byte B.
+
+ R(0) = (0 7) o (1 6) o (2 5) o (3 4)
+ R(1) = (8 15) o (9 14) o (10 13) o (11 12)
+
+ Notice that R o R = id. */
+
+static double_int
+avr_revert_map (int b)
+{
+ int i;
+ double_int r = double_int_zero;
+
+ for (i = 16-1; i >= 0; i--)
+ r = avr_double_int_push_digit (r, 16, i >> 3 == b ? i ^ 7 : i);
+
+ return r;
+}
+
+
+/* Return the map R that swaps bit-chunks of size SIZE in byte B.
+
+ R(1,0) = (0 1) o (2 3) o (4 5) o (6 7)
+ R(1,1) = (8 9) o (10 11) o (12 13) o (14 15)
+
+ R(4,0) = (0 4) o (1 5) o (2 6) o (3 7)
+ R(4,1) = (8 12) o (9 13) o (10 14) o (11 15)
+
+ Notice that R o R = id. */
+
+static double_int
+avr_swap_map (int size, int b)
+{
+ int i;
+ double_int r = double_int_zero;
+
+ for (i = 16-1; i >= 0; i--)
+ r = avr_double_int_push_digit (r, 16, i ^ (i >> 3 == b ? size : 0));
+
+ return r;
+}
+
+
+/* Return Identity. */
+
+static double_int
+avr_id_map (void)
+{
+ int i;
+ double_int r = double_int_zero;
+
+ for (i = 16-1; i >= 0; i--)
+ r = avr_double_int_push_digit (r, 16, i);
+
+ return r;
+}
+
+
+enum
+ {
+ SIG_ID = 0,
+ /* for QI and HI */
+ SIG_ROL = 0xf,
+ SIG_REVERT_0 = 1 << 4,
+ SIG_SWAP1_0 = 1 << 5,
+ /* HI only */
+ SIG_REVERT_1 = 1 << 6,
+ SIG_SWAP1_1 = 1 << 7,
+ SIG_SWAP4_0 = 1 << 8,
+ SIG_SWAP4_1 = 1 << 9
+ };
+
+
+/* Return basic map with signature SIG. */
+
+static double_int
+avr_sig_map (int n ATTRIBUTE_UNUSED, int sig)
+{
+ if (sig == SIG_ID) return avr_id_map ();
+ else if (sig == SIG_REVERT_0) return avr_revert_map (0);
+ else if (sig == SIG_REVERT_1) return avr_revert_map (1);
+ else if (sig == SIG_SWAP1_0) return avr_swap_map (1, 0);
+ else if (sig == SIG_SWAP1_1) return avr_swap_map (1, 1);
+ else if (sig == SIG_SWAP4_0) return avr_swap_map (4, 0);
+ else if (sig == SIG_SWAP4_1) return avr_swap_map (4, 1);
+ else
+ gcc_unreachable();
+}
+
+
+/* Return the Hamming distance between the B-th byte of A and C. */
+
+static bool
+avr_map_hamming_byte (int n, int b, double_int a, double_int c, bool strict)
+{
+ int i, hamming = 0;
+
+ for (i = 8*b; i < n && i < 8*b + 8; i++)
+ {
+ int ai = avr_map (a, i);
+ int ci = avr_map (c, i);
+
+ hamming += ai != ci && (strict || (ai < n && ci < n));
+ }
+
+ return hamming;
+}
+
+
+/* Return the non-strict Hamming distance between A and B. */
+
+#define avr_map_hamming_nonstrict(N,A,B) \
+ (+ avr_map_hamming_byte (N, 0, A, B, false) \
+ + avr_map_hamming_byte (N, 1, A, B, false))
+
+
+/* Return TRUE iff A and B represent the same mapping. */
+
+#define avr_map_equal_p(N,A,B) (0 == avr_map_hamming_nonstrict (N, A, B))
+
+
+/* Return TRUE iff A is a map of signature S. Notice that there is no
+ 1:1 correspondance between maps and signatures and thus this is
+ only supported for basic signatures recognized by avr_sig_map(). */
+
+#define avr_map_sig_p(N,A,S) avr_map_equal_p (N, A, avr_sig_map (N, S))
+
+
+/* Swap odd/even bits of ld-reg %0: %0 = bit-swap (%0) */
+
+static const char*
+avr_out_swap_bits (rtx *xop, int *plen)
+{
+ xop[1] = tmp_reg_rtx;
+
+ return avr_asm_len ("mov %1,%0" CR_TAB
+ "andi %0,0xaa" CR_TAB
+ "eor %1,%0" CR_TAB
+ "lsr %0" CR_TAB
+ "lsl %1" CR_TAB
+ "or %0,%1", xop, plen, 6);
+}
+
+/* Revert bit order: %0 = Revert (%1) with %0 != %1 and clobber %1 */
+
+static const char*
+avr_out_revert_bits (rtx *xop, int *plen)
+{
+ return avr_asm_len ("inc __zero_reg__" "\n"
+ "0:\tror %1" CR_TAB
+ "rol %0" CR_TAB
+ "lsl __zero_reg__" CR_TAB
+ "brne 0b", xop, plen, 5);
+}
+
+
+/* If OUT_P = true: Output BST/BLD instruction according to MAP.
+ If OUT_P = false: Just dry-run and fix XOP[1] to resolve
+ early-clobber conflicts if XOP[0] = XOP[1]. */
+
+static void
+avr_move_bits (rtx *xop, double_int map, int n_bits, bool out_p, int *plen)
+{
+ int bit_dest, b, clobber = 0;
+
+ /* T-flag contains this bit of the source, i.e. of XOP[1] */
+ int t_bit_src = -1;
+
+ if (!optimize && !out_p)
+ {
+ avr_asm_len ("mov __tmp_reg__,%1", xop, plen, 1);
+ xop[1] = tmp_reg_rtx;
+ return;
+ }
+
+ /* We order the operations according to the requested source bit b. */
+
+ for (b = 0; b < n_bits; b++)
+ for (bit_dest = 0; bit_dest < n_bits; bit_dest++)
+ {
+ int bit_src = avr_map (map, bit_dest);
+
+ if (b != bit_src
+ /* Same position: No need to copy as the caller did MOV. */
+ || bit_dest == bit_src
+ /* Accessing bits 8..f for 8-bit version is void. */
+ || bit_src >= n_bits)
+ continue;
+
+ if (t_bit_src != bit_src)
+ {
+ /* Source bit is not yet in T: Store it to T. */
+
+ t_bit_src = bit_src;
+
+ if (out_p)
+ {
+ xop[2] = GEN_INT (bit_src);
+ avr_asm_len ("bst %T1%T2", xop, plen, 1);
+ }
+ else if (clobber & (1 << bit_src))
+ {
+ /* Bit to be read was written already: Backup input
+ to resolve early-clobber conflict. */
+
+ avr_asm_len ("mov __tmp_reg__,%1", xop, plen, 1);
+ xop[1] = tmp_reg_rtx;
+ return;
+ }
+ }
+
+ /* Load destination bit with T. */
+
+ if (out_p)
+ {
+ xop[2] = GEN_INT (bit_dest);
+ avr_asm_len ("bld %T0%T2", xop, plen, 1);
+ }
+
+ clobber |= 1 << bit_dest;
+ }
+}
+
+
+/* Print assembler code for `map_bitsqi' and `map_bitshi'. */
+
+const char*
+avr_out_map_bits (rtx insn, rtx *operands, int *plen)
+{
+ bool copy_0, copy_1;
+ int n_bits = GET_MODE_BITSIZE (GET_MODE (operands[0]));
+ double_int map = rtx_to_double_int (operands[1]);
+ rtx xop[3];
+
+ xop[0] = operands[0];
+ xop[1] = operands[2];
+
+ if (plen)
+ *plen = 0;
+ else if (flag_print_asm_name)
+ avr_fdump (asm_out_file, ASM_COMMENT_START "%X\n", map);
+
+ switch (n_bits)
+ {
+ default:
+ gcc_unreachable();
+
+ case 8:
+ if (avr_map_sig_p (n_bits, map, SIG_SWAP1_0))
+ {
+ return avr_out_swap_bits (xop, plen);
+ }
+ else if (avr_map_sig_p (n_bits, map, SIG_REVERT_0))
+ {
+ if (REGNO (xop[0]) == REGNO (xop[1])
+ || !reg_unused_after (insn, xop[1]))
+ {
+ avr_asm_len ("mov __tmp_reg__,%1", xop, plen, 1);
+ xop[1] = tmp_reg_rtx;
+ }
+
+ return avr_out_revert_bits (xop, plen);
+ }
+
+ break; /* 8 */
+
+ case 16:
+
+ break; /* 16 */
+ }
+
+ /* Copy whole byte is cheaper than moving bits that stay at the same
+ position. Some bits in a byte stay at the same position iff the
+ strict Hamming distance to Identity is not 8. */
+
+ copy_0 = 8 != avr_map_hamming_byte (n_bits, 0, map, avr_id_map(), true);
+ copy_1 = 8 != avr_map_hamming_byte (n_bits, 1, map, avr_id_map(), true);
+
+ /* Perform the move(s) just worked out. */
+
+ if (n_bits == 8)
+ {
+ if (REGNO (xop[0]) == REGNO (xop[1]))
+ {
+ /* Fix early-clobber clashes.
+ Notice XOP[0] hat no eary-clobber in its constraint. */
+
+ avr_move_bits (xop, map, n_bits, false, plen);
+ }
+ else if (copy_0)
+ {
+ avr_asm_len ("mov %0,%1", xop, plen, 1);
+ }
+ }
+ else if (AVR_HAVE_MOVW && copy_0 && copy_1)
+ {
+ avr_asm_len ("movw %A0,%A1", xop, plen, 1);
+ }
+ else
+ {
+ if (copy_0)
+ avr_asm_len ("mov %A0,%A1", xop, plen, 1);
+
+ if (copy_1)
+ avr_asm_len ("mov %B0,%B1", xop, plen, 1);
+ }
+
+ /* Move individual bits. */
+
+ avr_move_bits (xop, map, n_bits, true, plen);
+
+ return "";
+}
+
+
/* IDs for all the AVR builtins. */
enum avr_builtin_id
@@ -8665,6 +10234,8 @@ enum avr_builtin_id
AVR_BUILTIN_WDR,
AVR_BUILTIN_SLEEP,
AVR_BUILTIN_SWAP,
+ AVR_BUILTIN_MAP8,
+ AVR_BUILTIN_MAP16,
AVR_BUILTIN_FMUL,
AVR_BUILTIN_FMULS,
AVR_BUILTIN_FMULSU,
@@ -8721,6 +10292,18 @@ avr_init_builtins (void)
long_unsigned_type_node,
NULL_TREE);
+ tree uchar_ftype_ulong_uchar
+ = build_function_type_list (unsigned_char_type_node,
+ long_unsigned_type_node,
+ unsigned_char_type_node,
+ NULL_TREE);
+
+ tree uint_ftype_ullong_uint
+ = build_function_type_list (unsigned_type_node,
+ long_long_unsigned_type_node,
+ unsigned_type_node,
+ NULL_TREE);
+
DEF_BUILTIN ("__builtin_avr_nop", void_ftype_void, AVR_BUILTIN_NOP);
DEF_BUILTIN ("__builtin_avr_sei", void_ftype_void, AVR_BUILTIN_SEI);
DEF_BUILTIN ("__builtin_avr_cli", void_ftype_void, AVR_BUILTIN_CLI);
@@ -8737,6 +10320,11 @@ avr_init_builtins (void)
DEF_BUILTIN ("__builtin_avr_fmulsu", int_ftype_char_uchar,
AVR_BUILTIN_FMULSU);
+ DEF_BUILTIN ("__builtin_avr_map8", uchar_ftype_ulong_uchar,
+ AVR_BUILTIN_MAP8);
+ DEF_BUILTIN ("__builtin_avr_map16", uint_ftype_ullong_uint,
+ AVR_BUILTIN_MAP16);
+
avr_init_builtin_int24 ();
}
@@ -8760,7 +10348,9 @@ bdesc_2arg[] =
{
{ CODE_FOR_fmul, "__builtin_avr_fmul", AVR_BUILTIN_FMUL },
{ CODE_FOR_fmuls, "__builtin_avr_fmuls", AVR_BUILTIN_FMULS },
- { CODE_FOR_fmulsu, "__builtin_avr_fmulsu", AVR_BUILTIN_FMULSU }
+ { CODE_FOR_fmulsu, "__builtin_avr_fmulsu", AVR_BUILTIN_FMULSU },
+ { CODE_FOR_map_bitsqi, "__builtin_avr_map8", AVR_BUILTIN_MAP8 },
+ { CODE_FOR_map_bitshi, "__builtin_avr_map16", AVR_BUILTIN_MAP16 }
};
/* Subroutine of avr_expand_builtin to take care of unop insns. */
@@ -8876,6 +10466,7 @@ avr_expand_builtin (tree exp, rtx target,
size_t i;
const struct avr_builtin_description *d;
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+ const char* bname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
unsigned int id = DECL_FUNCTION_CODE (fndecl);
tree arg0;
rtx op0;
@@ -8908,12 +10499,37 @@ 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 ("%s expects a compile time integer constant", bname);
avr_expand_delay_cycles (op0);
return 0;
}
+
+ case AVR_BUILTIN_MAP8:
+ {
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+
+ if (!CONST_INT_P (op0))
+ {
+ error ("%s expects a compile time long integer constant"
+ " as first argument", bname);
+ return target;
+ }
+ }
+
+ case AVR_BUILTIN_MAP16:
+ {
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+
+ if (!const_double_operand (op0, VOIDmode))
+ {
+ error ("%s expects a compile time long long integer constant"
+ " as first argument", bname);
+ return target;
+ }
+ }
}
for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h
index 7a3bc738e92..96133b8da28 100644
--- a/gcc/config/avr/avr.h
+++ b/gcc/config/avr/avr.h
@@ -23,7 +23,8 @@ along with GCC; see the file COPYING3. If not see
/* Names to predefine in the preprocessor for this target machine. */
-struct base_arch_s {
+struct base_arch_s
+{
/* Assembler only. */
int asm_only;
@@ -54,6 +55,13 @@ struct base_arch_s {
/* Default start of data section address for architecture. */
int default_data_section_start;
+ /* Offset between SFR address and RAM address:
+ SFR-address = RAM-address - sfr_offset */
+ int sfr_offset;
+
+ /* Number of 64k segments in the flash. */
+ int n_segments;
+
const char *const macro;
/* Architecture name. */
@@ -131,6 +139,8 @@ extern const struct base_arch_s avr_arch_types[];
#define AVR_HAVE_MUL (avr_current_arch->have_mul)
#define AVR_HAVE_MOVW (avr_current_arch->have_movw_lpmx)
#define AVR_HAVE_LPMX (avr_current_arch->have_movw_lpmx)
+#define AVR_HAVE_ELPM (avr_current_arch->have_elpm)
+#define AVR_HAVE_ELPMX (avr_current_arch->have_elpmx)
#define AVR_HAVE_RAMPZ (avr_current_arch->have_elpm)
#define AVR_HAVE_EIJMP_EICALL (avr_current_arch->have_eijmp_eicall)
#define AVR_HAVE_8BIT_SP (avr_current_device->short_sp || TARGET_TINY_STACK)
@@ -391,6 +401,20 @@ typedef struct avr_args {
#define NO_FUNCTION_CSE
+
+#define ADDR_SPACE_PGM 1
+#define ADDR_SPACE_PGM1 2
+#define ADDR_SPACE_PGM2 3
+#define ADDR_SPACE_PGM3 4
+#define ADDR_SPACE_PGM4 5
+#define ADDR_SPACE_PGM5 6
+#define ADDR_SPACE_PGMX 7
+
+#define REGISTER_TARGET_PRAGMAS() \
+ do { \
+ avr_register_target_pragmas(); \
+ } while (0)
+
#define TEXT_SECTION_ASM_OP "\t.text"
#define DATA_SECTION_ASM_OP "\t.data"
@@ -637,3 +661,5 @@ struct GTY(()) machine_function
#define PUSH_ROUNDING(X) (X)
#define ACCUMULATE_OUTGOING_ARGS avr_accumulate_outgoing_args()
+
+#define INIT_EXPANDERS avr_init_expanders()
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 59330104fa0..bddfe933ee6 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -28,9 +28,21 @@
;; j Branch condition.
;; k Reverse branch condition.
;;..m..Constant Direct Data memory address.
+;; i Print the SFR address quivalent of a CONST_INT or a CONST_INT
+;; RAM address. The resulting addres is suitable to be used in IN/OUT.
;; o Displacement for (mem (plus (reg) (const_int))) operands.
;; p POST_INC or PRE_DEC address as a pointer (X, Y, Z)
;; r POST_INC or PRE_DEC address as a register (r26, r28, r30)
+;; T/T Print operand suitable for BLD/BST instruction, i.e. register and
+;; bit number. This gets 2 operands: The first %T gets a REG_P and
+;; just cashes the operand for the next %T. The second %T gets
+;; a CONST_INT that represents a bit position.
+;; Example: With %0 = (reg:HI 18) and %1 = (const_int 13)
+;; "%T0%T1" it will print "r19,5".
+;; Notice that you must not write a comma between %T0 and %T1.
+;; T/t Similar to above, but don't print the comma and the bit number.
+;; Example: With %0 = (reg:HI 18) and %1 = (const_int 13)
+;; "%T0%t1" it will print "r19".
;;..x..Constant Direct Program memory address.
;; ~ Output 'r' if not AVR_HAVE_JMP_CALL.
;; ! Output 'e' if AVR_HAVE_EIJMP_EICALL.
@@ -42,21 +54,27 @@
(REG_Z 30)
(REG_W 24)
(REG_SP 32)
+ (LPM_REGNO 0) ; implicit target register of LPM
(TMP_REGNO 0) ; temporary register r0
(ZERO_REGNO 1) ; zero register r1
-
- (SREG_ADDR 0x5F)
- (RAMPZ_ADDR 0x5B)
+
+ ;; RAM addresses of some SFRs common to all Devices.
+
+ (SREG_ADDR 0x5F) ; Status Register
+ (SP_ADDR 0x5D) ; Stack Pointer
+ (RAMPZ_ADDR 0x5B) ; Address' high part when loading via ELPM
])
(define_c_enum "unspec"
[UNSPEC_STRLEN
+ UNSPEC_MOVMEM
UNSPEC_INDEX_JMP
UNSPEC_FMUL
UNSPEC_FMULS
UNSPEC_FMULSU
UNSPEC_COPYSIGN
UNSPEC_IDENTITY
+ UNSPEC_MAP_BITS
])
(define_c_enum "unspecv"
@@ -127,24 +145,25 @@
"out_bitop, out_plus, out_plus_noclobber, addto_sp,
tsthi, tstpsi, tstsi, compare, call,
mov8, mov16, mov24, mov32, reload_in16, reload_in24, reload_in32,
+ xload, movmem,
ashlqi, ashrqi, lshrqi,
ashlhi, ashrhi, lshrhi,
ashlsi, ashrsi, lshrsi,
ashlpsi, ashrpsi, lshrpsi,
+ map_bits,
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
+;; 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
+;; lpm : ISA has no LPMX lpmx : ISA has LPMX
+;; elpm : ISA has ELPM but no ELPMX elpmx : ISA has ELPMX
(define_attr "isa"
- "mov,movw, rjmp,jmp, ijmp,eijmp,
+ "mov,movw, rjmp,jmp, ijmp,eijmp, lpm,lpmx, elpm,elpmx,
standard"
(const_string "standard"))
@@ -175,6 +194,22 @@
(and (eq_attr "isa" "eijmp")
(match_test "AVR_HAVE_EIJMP_EICALL"))
(const_int 1)
+
+ (and (eq_attr "isa" "lpm")
+ (match_test "!AVR_HAVE_LPMX"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "lpmx")
+ (match_test "AVR_HAVE_LPMX"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "elpm")
+ (match_test "AVR_HAVE_ELPM && !AVR_HAVE_ELPMX"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "elpmx")
+ (match_test "AVR_HAVE_ELPMX"))
+ (const_int 1)
] (const_int 0)))
@@ -242,12 +277,10 @@
;; even though its function is identical to that in builtins.c
(define_expand "nonlocal_goto"
- [
- (use (match_operand 0 "general_operand"))
- (use (match_operand 1 "general_operand"))
- (use (match_operand 2 "general_operand"))
- (use (match_operand 3 "general_operand"))
- ]
+ [(use (match_operand 0 "general_operand"))
+ (use (match_operand 1 "general_operand"))
+ (use (match_operand 2 "general_operand"))
+ (use (match_operand 3 "general_operand"))]
""
{
rtx r_label = copy_to_reg (operands[1]);
@@ -315,6 +348,168 @@
"")
;;========================================================================
+;; Move stuff around
+
+(define_expand "load<mode>_libgcc"
+ [(set (match_dup 3)
+ (match_dup 2))
+ (set (reg:MOVMODE 22)
+ (match_operand:MOVMODE 1 "memory_operand" ""))
+ (set (match_operand:MOVMODE 0 "register_operand" "")
+ (reg:MOVMODE 22))]
+ "avr_load_libgcc_p (operands[1])"
+ {
+ operands[3] = gen_rtx_REG (HImode, REG_Z);
+ operands[2] = force_operand (XEXP (operands[1], 0), NULL_RTX);
+ operands[1] = replace_equiv_address (operands[1], operands[3]);
+ set_mem_addr_space (operands[1], ADDR_SPACE_PGM);
+ })
+
+(define_insn "load_<mode>_libgcc"
+ [(set (reg:MOVMODE 22)
+ (match_operand:MOVMODE 0 "memory_operand" "m,m"))]
+ "avr_load_libgcc_p (operands[0])
+ && REG_P (XEXP (operands[0], 0))
+ && REG_Z == REGNO (XEXP (operands[0], 0))"
+ {
+ operands[0] = GEN_INT (GET_MODE_SIZE (<MODE>mode));
+ return "%~call __load_%0";
+ }
+ [(set_attr "length" "1,2")
+ (set_attr "isa" "rjmp,jmp")
+ (set_attr "cc" "clobber")])
+
+
+(define_insn_and_split "xload8_A"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (match_operand:QI 1 "memory_operand" "m"))
+ (clobber (reg:HI REG_Z))]
+ "can_create_pseudo_p()
+ && avr_mem_pgmx_p (operands[1])
+ && REG_P (XEXP (operands[1], 0))"
+ { gcc_unreachable(); }
+ "&& 1"
+ [(clobber (const_int 0))]
+ {
+ rtx insn, addr = XEXP (operands[1], 0);
+ rtx hi8 = gen_reg_rtx (QImode);
+ rtx reg_z = gen_rtx_REG (HImode, REG_Z);
+
+ emit_move_insn (reg_z, simplify_gen_subreg (HImode, addr, PSImode, 0));
+ emit_move_insn (hi8, simplify_gen_subreg (QImode, addr, PSImode, 2));
+
+ insn = emit_insn (gen_xload_8 (operands[0], hi8));
+ set_mem_addr_space (SET_SRC (single_set (insn)),
+ MEM_ADDR_SPACE (operands[1]));
+ DONE;
+ })
+
+(define_insn_and_split "xload<mode>_A"
+ [(set (match_operand:MOVMODE 0 "register_operand" "=r")
+ (match_operand:MOVMODE 1 "memory_operand" "m"))
+ (clobber (reg:QI 21))
+ (clobber (reg:HI REG_Z))]
+ "QImode != <MODE>mode
+ && can_create_pseudo_p()
+ && avr_mem_pgmx_p (operands[1])
+ && REG_P (XEXP (operands[1], 0))"
+ { gcc_unreachable(); }
+ "&& 1"
+ [(clobber (const_int 0))]
+ {
+ rtx addr = XEXP (operands[1], 0);
+ rtx reg_z = gen_rtx_REG (HImode, REG_Z);
+ rtx addr_hi8 = simplify_gen_subreg (QImode, addr, PSImode, 2);
+ addr_space_t as = MEM_ADDR_SPACE (operands[1]);
+ rtx hi8, insn;
+
+ emit_move_insn (reg_z, simplify_gen_subreg (HImode, addr, PSImode, 0));
+
+ if (avr_xload_libgcc_p (<MODE>mode))
+ {
+ emit_move_insn (gen_rtx_REG (QImode, 21), addr_hi8);
+ insn = emit_insn (gen_xload_<mode>_libgcc ());
+ emit_move_insn (operands[0], gen_rtx_REG (<MODE>mode, 22));
+ }
+ else if (avr_current_arch->n_segments == 1
+ && GET_MODE_SIZE (<MODE>mode) > 2
+ && !AVR_HAVE_LPMX)
+ {
+ rtx src = gen_rtx_MEM (<MODE>mode, reg_z);
+
+ as = ADDR_SPACE_PGM;
+ insn = emit_insn (gen_load_<mode>_libgcc (src));
+ emit_move_insn (operands[0], gen_rtx_REG (<MODE>mode, 22));
+ }
+ else
+ {
+ hi8 = gen_reg_rtx (QImode);
+ emit_move_insn (hi8, addr_hi8);
+ insn = emit_insn (gen_xload_<mode> (operands[0], hi8));
+ }
+
+ set_mem_addr_space (SET_SRC (single_set (insn)), as);
+
+ DONE;
+ })
+
+;; Move value from address space pgmx to a register
+;; These insns must be prior to respective generic move insn.
+
+(define_insn "xload_8"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (mem:QI (lo_sum:PSI (match_operand:QI 1 "register_operand" "r")
+ (reg:HI REG_Z))))]
+ ""
+ {
+ return avr_out_xload (insn, operands, NULL);
+ }
+ [(set_attr "adjust_len" "xload")
+ (set_attr "cc" "clobber")])
+
+;; "xload_hi_libgcc"
+;; "xload_psi_libgcc"
+;; "xload_si_libgcc"
+;; "xload_sf_libgcc"
+(define_insn "xload_<mode>_libgcc"
+ [(set (reg:MOVMODE 22)
+ (mem:MOVMODE (lo_sum:PSI (reg:QI 21)
+ (reg:HI REG_Z))))
+ (clobber (reg:QI 21))
+ (clobber (reg:HI REG_Z))]
+ "<MODE>mode != QImode
+ && avr_xload_libgcc_p (<MODE>mode)"
+ {
+ rtx x_bytes = GEN_INT (GET_MODE_SIZE (<MODE>mode));
+
+ /* Devices with ELPM* also have CALL. */
+
+ output_asm_insn ("call __xload_%0", &x_bytes);
+ return "";
+ }
+ [(set_attr "length" "2")
+ (set_attr "cc" "clobber")])
+
+;; "xload_hi"
+;; "xload_psi"
+;; "xload_si"
+;; "xload_sf"
+(define_insn "xload_<mode>"
+ [(set (match_operand:MOVMODE 0 "register_operand" "=r")
+ (mem:MOVMODE (lo_sum:PSI (match_operand:QI 1 "register_operand" "r")
+ (reg:HI REG_Z))))
+ (clobber (scratch:HI))
+ (clobber (reg:HI REG_Z))]
+ "<MODE>mode != QImode
+ && !avr_xload_libgcc_p (<MODE>mode)"
+ {
+ return avr_out_xload (insn, operands, NULL);
+ }
+ [(set_attr "adjust_len" "xload")
+ (set_attr "cc" "clobber")])
+
+
+;; General move expanders
;; "movqi"
;; "movhi"
@@ -327,12 +522,40 @@
(match_operand:MOVMODE 1 "general_operand" ""))]
""
{
- /* One of the ops has to be in a register. */
- if (!register_operand (operands[0], <MODE>mode)
- && !(register_operand (operands[1], <MODE>mode)
- || CONST0_RTX (<MODE>mode) == operands[1]))
+ rtx dest = operands[0];
+ rtx src = operands[1];
+
+ if (avr_mem_pgm_p (dest))
+ DONE;
+
+ /* One of the operands has to be in a register. */
+ if (!register_operand (dest, <MODE>mode)
+ && !(register_operand (src, <MODE>mode)
+ || src == CONST0_RTX (<MODE>mode)))
+ {
+ operands[1] = src = copy_to_mode_reg (<MODE>mode, src);
+ }
+
+ if (avr_mem_pgmx_p (src))
+ {
+ rtx addr = XEXP (src, 0);
+
+ if (!REG_P (addr))
+ src = replace_equiv_address (src, copy_to_mode_reg (PSImode, addr));
+
+ if (QImode == <MODE>mode)
+ emit_insn (gen_xload8_A (dest, src));
+ else
+ emit_insn (gen_xload<mode>_A (dest, src));
+
+ DONE;
+ }
+
+ if (avr_load_libgcc_p (src))
{
- operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
+ /* For the small devices, do loads per libgcc call. */
+ emit_insn (gen_load<mode>_libgcc (dest, src));
+ DONE;
}
})
@@ -346,11 +569,14 @@
;; so this may still be a win for registers live across function calls.
(define_insn "movqi_insn"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=r,d,Qm,r,q,r,*r")
- (match_operand:QI 1 "general_operand" "rL,i,rL,Qm,r,q,i"))]
- "(register_operand (operands[0],QImode)
- || register_operand (operands[1], QImode) || const0_rtx == operands[1])"
- "* return output_movqi (insn, operands, NULL);"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=r ,d,Qm,r ,q,r,*r")
+ (match_operand:QI 1 "nox_general_operand" "rL,i,rL,Qm,r,q,i"))]
+ "register_operand (operands[0], QImode)
+ || register_operand (operands[1], QImode)
+ || const0_rtx == operands[1]"
+ {
+ return output_movqi (insn, operands, NULL);
+ }
[(set_attr "length" "1,1,5,5,1,1,4")
(set_attr "adjust_len" "mov8")
(set_attr "cc" "none,none,clobber,clobber,none,none,clobber")])
@@ -425,14 +651,17 @@
(set_attr "cc" "none")])
(define_insn "*movhi"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,d,*r,q,r")
- (match_operand:HI 1 "general_operand" "r,L,m,rL,i,i,r,q"))]
- "(register_operand (operands[0],HImode)
- || register_operand (operands[1],HImode) || const0_rtx == operands[1])"
- "* return output_movhi (insn, operands, NULL);"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m ,d,*r,q,r")
+ (match_operand:HI 1 "nox_general_operand" "r,L,m,rL,i,i ,r,q"))]
+ "register_operand (operands[0], HImode)
+ || register_operand (operands[1], HImode)
+ || const0_rtx == operands[1]"
+ {
+ return output_movhi (insn, operands, NULL);
+ }
[(set_attr "length" "2,2,6,7,2,6,5,2")
(set_attr "adjust_len" "mov16")
- (set_attr "cc" "none,clobber,clobber,clobber,none,clobber,none,none")])
+ (set_attr "cc" "none,none,clobber,clobber,none,clobber,none,none")])
(define_peephole2 ; movw
[(set (match_operand:QI 0 "even_register_operand" "")
@@ -462,6 +691,40 @@
operands[5] = gen_rtx_REG (HImode, REGNO (operands[3]));
})
+;; For LPM loads from AS1 we split
+;; R = *Z
+;; to
+;; R = *Z++
+;; Z = Z - sizeof (R)
+;;
+;; so that the second instruction can be optimized out.
+
+(define_split ; "split-lpmx"
+ [(set (match_operand:HISI 0 "register_operand" "")
+ (match_operand:HISI 1 "memory_operand" ""))]
+ "reload_completed
+ && AVR_HAVE_LPMX"
+ [(set (match_dup 0)
+ (match_dup 2))
+ (set (match_dup 3)
+ (plus:HI (match_dup 3)
+ (match_dup 4)))]
+ {
+ rtx addr = XEXP (operands[1], 0);
+
+ if (!avr_mem_pgm_p (operands[1])
+ || !REG_P (addr)
+ || reg_overlap_mentioned_p (addr, operands[0]))
+ {
+ FAIL;
+ }
+
+ operands[2] = replace_equiv_address (operands[1],
+ gen_rtx_POST_INC (Pmode, addr));
+ operands[3] = addr;
+ operands[4] = gen_int_mode (-GET_MODE_SIZE (<MODE>mode), HImode);
+ })
+
;;==========================================================================
;; xpointer move (24 bit)
@@ -492,7 +755,7 @@
(define_insn "*movpsi"
[(set (match_operand:PSI 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r")
- (match_operand:PSI 1 "general_operand" "r,L,Qm,rL,i ,i"))]
+ (match_operand:PSI 1 "nox_general_operand" "r,L,Qm,rL,i ,i"))]
"register_operand (operands[0], PSImode)
|| register_operand (operands[1], PSImode)
|| const0_rtx == operands[1]"
@@ -501,7 +764,7 @@
}
[(set_attr "length" "3,3,8,9,4,10")
(set_attr "adjust_len" "mov24")
- (set_attr "cc" "none,set_zn,clobber,clobber,clobber,clobber")])
+ (set_attr "cc" "none,none,clobber,clobber,none,clobber")])
;;==========================================================================
;; move double word (32 bit)
@@ -532,23 +795,24 @@
(define_insn "*movsi"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,Qm,!d,r")
- (match_operand:SI 1 "general_operand" "r,L,Qm,rL,i,i"))]
- "(register_operand (operands[0],SImode)
- || register_operand (operands[1],SImode) || const0_rtx == operands[1])"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r")
+ (match_operand:SI 1 "nox_general_operand" "r,L,Qm,rL,i ,i"))]
+ "register_operand (operands[0], SImode)
+ || register_operand (operands[1], SImode)
+ || const0_rtx == operands[1]"
{
return output_movsisf (insn, operands, NULL);
}
[(set_attr "length" "4,4,8,9,4,10")
(set_attr "adjust_len" "mov32")
- (set_attr "cc" "none,set_zn,clobber,clobber,clobber,clobber")])
+ (set_attr "cc" "none,none,clobber,clobber,none,clobber")])
;; fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
;; move floating point numbers (32 bit)
(define_insn "*movsf"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,Qm,!d,r")
- (match_operand:SF 1 "general_operand" "r,G,Qm,rG,F,F"))]
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r")
+ (match_operand:SF 1 "nox_general_operand" "r,G,Qm,rG,F ,F"))]
"register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode)
|| operands[1] == CONST0_RTX (SFmode)"
@@ -557,7 +821,7 @@
}
[(set_attr "length" "4,4,8,9,4,10")
(set_attr "adjust_len" "mov32")
- (set_attr "cc" "none,set_zn,clobber,clobber,clobber,clobber")])
+ (set_attr "cc" "none,none,clobber,clobber,none,clobber")])
(define_peephole2 ; *reload_insf
[(match_scratch:QI 2 "d")
@@ -585,166 +849,164 @@
;;=========================================================================
;; move string (like memcpy)
-;; implement as RTL loop
(define_expand "movmemhi"
[(parallel [(set (match_operand:BLK 0 "memory_operand" "")
- (match_operand:BLK 1 "memory_operand" ""))
- (use (match_operand:HI 2 "const_int_operand" ""))
- (use (match_operand:HI 3 "const_int_operand" ""))])]
+ (match_operand:BLK 1 "memory_operand" ""))
+ (use (match_operand:HI 2 "const_int_operand" ""))
+ (use (match_operand:HI 3 "const_int_operand" ""))])]
""
- "{
- int prob;
- HOST_WIDE_INT count;
- enum machine_mode mode;
- rtx label = gen_label_rtx ();
- rtx loop_reg;
- rtx jump;
-
- /* Copy pointers into new psuedos - they will be changed. */
- rtx addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
- rtx addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
-
- /* Create rtx for tmp register - we use this as scratch. */
- rtx tmp_reg_rtx = gen_rtx_REG (QImode, TMP_REGNO);
-
- if (GET_CODE (operands[2]) != CONST_INT)
- FAIL;
-
- count = INTVAL (operands[2]);
- if (count <= 0)
+ {
+ if (avr_emit_movmemhi (operands))
+ DONE;
+
FAIL;
+ })
- /* Work out branch probability for latter use. */
- prob = REG_BR_PROB_BASE - REG_BR_PROB_BASE / count;
-
- /* See if constant fit 8 bits. */
- mode = (count < 0x100) ? QImode : HImode;
- /* Create loop counter register. */
- loop_reg = copy_to_mode_reg (mode, gen_int_mode (count, mode));
-
- /* Now create RTL code for move loop. */
- /* Label at top of loop. */
- emit_label (label);
-
- /* Move one byte into scratch and inc pointer. */
- emit_move_insn (tmp_reg_rtx, gen_rtx_MEM (QImode, addr1));
- emit_move_insn (addr1, gen_rtx_PLUS (Pmode, addr1, const1_rtx));
-
- /* Move to mem and inc pointer. */
- emit_move_insn (gen_rtx_MEM (QImode, addr0), tmp_reg_rtx);
- emit_move_insn (addr0, gen_rtx_PLUS (Pmode, addr0, const1_rtx));
+(define_mode_attr MOVMEM_r_d [(QI "r")
+ (HI "d")])
+
+;; $0, $4 : & dest
+;; $1, $5 : & src
+;; $2 : Address Space
+;; $3, $7 : Loop register
+;; $6 : Scratch register
+
+;; "movmem_qi"
+;; "movmem_hi"
+(define_insn "movmem_<mode>"
+ [(set (mem:BLK (match_operand:HI 0 "register_operand" "x"))
+ (mem:BLK (match_operand:HI 1 "register_operand" "z")))
+ (unspec [(match_operand:QI 2 "const_int_operand" "LP")]
+ UNSPEC_MOVMEM)
+ (use (match_operand:QIHI 3 "register_operand" "<MOVMEM_r_d>"))
+ (clobber (match_operand:HI 4 "register_operand" "=0"))
+ (clobber (match_operand:HI 5 "register_operand" "=1"))
+ (clobber (match_operand:QI 6 "register_operand" "=&r"))
+ (clobber (match_operand:QIHI 7 "register_operand" "=3"))]
+ ""
+ {
+ return avr_out_movmem (insn, operands, NULL);
+ }
+ [(set_attr "adjust_len" "movmem")
+ (set_attr "cc" "clobber")])
- /* Decrement count. */
- emit_move_insn (loop_reg, gen_rtx_PLUS (mode, loop_reg, constm1_rtx));
+;; Ditto and
+;; $8, $9 : hh8 (& src)
+;; $10 : RAMPZ_ADDR
+
+;; "movmem_qi_elpm"
+;; "movmem_hi_elpm"
+(define_insn "movmem_<mode>_elpm"
+ [(set (mem:BLK (match_operand:HI 0 "register_operand" "x"))
+ (mem:BLK (lo_sum:PSI (match_operand:QI 8 "register_operand" "r")
+ (match_operand:HI 1 "register_operand" "z"))))
+ (unspec [(match_operand:QI 2 "const_int_operand" "n")]
+ UNSPEC_MOVMEM)
+ (use (match_operand:QIHI 3 "register_operand" "<MOVMEM_r_d>"))
+ (clobber (match_operand:HI 4 "register_operand" "=0"))
+ (clobber (match_operand:HI 5 "register_operand" "=1"))
+ (clobber (match_operand:QI 6 "register_operand" "=&r"))
+ (clobber (match_operand:QIHI 7 "register_operand" "=3"))
+ (clobber (match_operand:QI 9 "register_operand" "=8"))
+ (clobber (mem:QI (match_operand:QI 10 "io_address_operand" "n")))]
+ ""
+ {
+ return avr_out_movmem (insn, operands, NULL);
+ }
+ [(set_attr "adjust_len" "movmem")
+ (set_attr "cc" "clobber")])
- /* Compare with zero and jump if not equal. */
- emit_cmp_and_jump_insns (loop_reg, const0_rtx, NE, NULL_RTX, mode, 1,
- label);
- /* Set jump probability based on loop count. */
- jump = get_last_insn ();
- add_reg_note (jump, REG_BR_PROB, GEN_INT (prob));
- DONE;
-}")
-;; =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2
+;; =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2
;; memset (%0, %2, %1)
(define_expand "setmemhi"
[(parallel [(set (match_operand:BLK 0 "memory_operand" "")
- (match_operand 2 "const_int_operand" ""))
- (use (match_operand:HI 1 "const_int_operand" ""))
- (use (match_operand:HI 3 "const_int_operand" "n"))
- (clobber (match_scratch:HI 4 ""))
- (clobber (match_dup 5))])]
+ (match_operand 2 "const_int_operand" ""))
+ (use (match_operand:HI 1 "const_int_operand" ""))
+ (use (match_operand:HI 3 "const_int_operand" ""))
+ (clobber (match_scratch:HI 4 ""))
+ (clobber (match_dup 5))])]
""
- "{
- rtx addr0;
- enum machine_mode mode;
+ {
+ rtx addr0;
+ enum machine_mode mode;
- /* If value to set is not zero, use the library routine. */
- if (operands[2] != const0_rtx)
- FAIL;
+ /* If value to set is not zero, use the library routine. */
+ if (operands[2] != const0_rtx)
+ FAIL;
- if (!CONST_INT_P (operands[1]))
- FAIL;
+ if (!CONST_INT_P (operands[1]))
+ FAIL;
+
+ mode = u8_operand (operands[1], VOIDmode) ? QImode : HImode;
+ operands[5] = gen_rtx_SCRATCH (mode);
+ operands[1] = copy_to_mode_reg (mode,
+ gen_int_mode (INTVAL (operands[1]), mode));
+ addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
+ operands[0] = gen_rtx_MEM (BLKmode, addr0);
+ })
- mode = u8_operand (operands[1], VOIDmode) ? QImode : HImode;
- operands[5] = gen_rtx_SCRATCH (mode);
- operands[1] = copy_to_mode_reg (mode,
- gen_int_mode (INTVAL (operands[1]), mode));
- addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
- operands[0] = gen_rtx_MEM (BLKmode, addr0);
-}")
(define_insn "*clrmemqi"
[(set (mem:BLK (match_operand:HI 0 "register_operand" "e"))
- (const_int 0))
+ (const_int 0))
(use (match_operand:QI 1 "register_operand" "r"))
(use (match_operand:QI 2 "const_int_operand" "n"))
(clobber (match_scratch:HI 3 "=0"))
(clobber (match_scratch:QI 4 "=&1"))]
""
- "st %a0+,__zero_reg__
- dec %1
- brne .-6"
+ "0:\;st %a0+,__zero_reg__\;dec %1\;brne 0b"
[(set_attr "length" "3")
(set_attr "cc" "clobber")])
+
(define_insn "*clrmemhi"
[(set (mem:BLK (match_operand:HI 0 "register_operand" "e,e"))
- (const_int 0))
+ (const_int 0))
(use (match_operand:HI 1 "register_operand" "!w,d"))
(use (match_operand:HI 2 "const_int_operand" "n,n"))
(clobber (match_scratch:HI 3 "=0,0"))
(clobber (match_scratch:HI 4 "=&1,&1"))]
""
- "*{
- if (which_alternative==0)
- return (AS2 (st,%a0+,__zero_reg__) CR_TAB
- AS2 (sbiw,%A1,1) CR_TAB
- AS1 (brne,.-6));
- else
- return (AS2 (st,%a0+,__zero_reg__) CR_TAB
- AS2 (subi,%A1,1) CR_TAB
- AS2 (sbci,%B1,0) CR_TAB
- AS1 (brne,.-8));
-}"
+ "@
+ 0:\;st %a0+,__zero_reg__\;sbiw %A1,1\;brne 0b
+ 0:\;st %a0+,__zero_reg__\;subi %A1,1\;sbci %B1,0\;brne 0b"
[(set_attr "length" "3,4")
(set_attr "cc" "clobber,clobber")])
(define_expand "strlenhi"
- [(set (match_dup 4)
- (unspec:HI [(match_operand:BLK 1 "memory_operand" "")
- (match_operand:QI 2 "const_int_operand" "")
- (match_operand:HI 3 "immediate_operand" "")]
- UNSPEC_STRLEN))
- (set (match_dup 4) (plus:HI (match_dup 4)
- (const_int -1)))
- (set (match_operand:HI 0 "register_operand" "")
- (minus:HI (match_dup 4)
- (match_dup 5)))]
- ""
- "{
- rtx addr;
- if (operands[2] != const0_rtx)
- FAIL;
- addr = copy_to_mode_reg (Pmode, XEXP (operands[1],0));
- operands[1] = gen_rtx_MEM (BLKmode, addr);
- operands[5] = addr;
- operands[4] = gen_reg_rtx (HImode);
-}")
+ [(set (match_dup 4)
+ (unspec:HI [(match_operand:BLK 1 "memory_operand" "")
+ (match_operand:QI 2 "const_int_operand" "")
+ (match_operand:HI 3 "immediate_operand" "")]
+ UNSPEC_STRLEN))
+ (set (match_dup 4)
+ (plus:HI (match_dup 4)
+ (const_int -1)))
+ (set (match_operand:HI 0 "register_operand" "")
+ (minus:HI (match_dup 4)
+ (match_dup 5)))]
+ ""
+ {
+ rtx addr;
+ if (operands[2] != const0_rtx)
+ FAIL;
+ addr = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
+ operands[1] = gen_rtx_MEM (BLKmode, addr);
+ operands[5] = addr;
+ operands[4] = gen_reg_rtx (HImode);
+ })
(define_insn "*strlenhi"
- [(set (match_operand:HI 0 "register_operand" "=e")
- (unspec:HI [(mem:BLK (match_operand:HI 1 "register_operand" "%0"))
- (const_int 0)
- (match_operand:HI 2 "immediate_operand" "i")]
- UNSPEC_STRLEN))]
- ""
- "ld __tmp_reg__,%a0+
- tst __tmp_reg__
- brne .-6"
+ [(set (match_operand:HI 0 "register_operand" "=e")
+ (unspec:HI [(mem:BLK (match_operand:HI 1 "register_operand" "0"))
+ (const_int 0)
+ (match_operand:HI 2 "immediate_operand" "i")]
+ UNSPEC_STRLEN))]
+ ""
+ "0:\;ld __tmp_reg__,%a0+\;tst __tmp_reg__\;brne 0b"
[(set_attr "length" "3")
(set_attr "cc" "clobber")])
@@ -2770,7 +3032,7 @@
(const_int 15)))]
""
"bst %A0,0\;ror %B0\;ror %A0\;bld %B0,7"
- [(set_attr "length" "3")
+ [(set_attr "length" "4")
(set_attr "cc" "clobber")])
(define_insn "*rotlpsi2.1"
@@ -2868,10 +3130,8 @@
(define_expand "ashlqi3"
[(set (match_operand:QI 0 "register_operand" "")
- (ashift:QI (match_operand:QI 1 "register_operand" "")
- (match_operand:QI 2 "general_operand" "")))]
- ""
- "")
+ (ashift:QI (match_operand:QI 1 "register_operand" "")
+ (match_operand:QI 2 "nop_general_operand" "")))])
(define_split ; ashlqi3_const4
[(set (match_operand:QI 0 "d_register_operand" "")
@@ -2903,21 +3163,25 @@
"")
(define_insn "*ashlqi3"
- [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,!d,r,r")
- (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0,0,0")
- (match_operand:QI 2 "general_operand" "r,L,P,K,n,n,Qm")))]
+ [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,!d,r,r")
+ (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0 ,0,0")
+ (match_operand:QI 2 "nop_general_operand" "r,L,P,K,n ,n,Qm")))]
""
- "* return ashlqi3_out (insn, operands, NULL);"
+ {
+ return ashlqi3_out (insn, operands, NULL);
+ }
[(set_attr "length" "5,0,1,2,4,6,9")
(set_attr "adjust_len" "ashlqi")
(set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,set_czn,clobber")])
(define_insn "ashlhi3"
- [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r,r")
- (ashift:HI (match_operand:HI 1 "register_operand" "0,0,0,r,0,0,0")
- (match_operand:QI 2 "general_operand" "r,L,P,O,K,n,Qm")))]
+ [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r,r")
+ (ashift:HI (match_operand:HI 1 "register_operand" "0,0,0,r,0,0,0")
+ (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))]
""
- "* return ashlhi3_out (insn, operands, NULL);"
+ {
+ return ashlhi3_out (insn, operands, NULL);
+ }
[(set_attr "length" "6,0,2,2,4,10,10")
(set_attr "adjust_len" "ashlhi")
(set_attr "cc" "clobber,none,set_n,clobber,set_n,clobber,clobber")])
@@ -3005,11 +3269,13 @@
(define_insn "ashlsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r")
- (ashift:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
- (match_operand:QI 2 "general_operand" "r,L,P,O,K,n,Qm")))]
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r")
+ (ashift:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
+ (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))]
""
- "* return ashlsi3_out (insn, operands, NULL);"
+ {
+ return ashlsi3_out (insn, operands, NULL);
+ }
[(set_attr "length" "8,0,4,4,8,10,12")
(set_attr "adjust_len" "ashlsi")
(set_attr "cc" "clobber,none,set_n,clobber,set_n,clobber,clobber")])
@@ -3063,11 +3329,13 @@
(define_insn "*ashlhi3_const"
[(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r")
- (ashift:HI (match_operand:HI 1 "register_operand" "0,0,r,0,0")
- (match_operand:QI 2 "const_int_operand" "L,P,O,K,n")))
- (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))]
+ (ashift:HI (match_operand:HI 1 "register_operand" "0,0,r,0,0")
+ (match_operand:QI 2 "const_int_operand" "L,P,O,K,n")))
+ (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))]
"reload_completed"
- "* return ashlhi3_out (insn, operands, NULL);"
+ {
+ return ashlhi3_out (insn, operands, NULL);
+ }
[(set_attr "length" "0,2,2,4,10")
(set_attr "adjust_len" "ashlhi")
(set_attr "cc" "none,set_n,clobber,set_n,clobber")])
@@ -3084,11 +3352,13 @@
(define_insn "*ashlsi3_const"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (ashift:SI (match_operand:SI 1 "register_operand" "0,0,r,0")
- (match_operand:QI 2 "const_int_operand" "L,P,O,n")))
- (clobber (match_scratch:QI 3 "=X,X,X,&d"))]
+ (ashift:SI (match_operand:SI 1 "register_operand" "0,0,r,0")
+ (match_operand:QI 2 "const_int_operand" "L,P,O,n")))
+ (clobber (match_scratch:QI 3 "=X,X,X,&d"))]
"reload_completed"
- "* return ashlsi3_out (insn, operands, NULL);"
+ {
+ return ashlsi3_out (insn, operands, NULL);
+ }
[(set_attr "length" "0,4,4,10")
(set_attr "adjust_len" "ashlsi")
(set_attr "cc" "none,set_n,clobber,clobber")])
@@ -3109,21 +3379,25 @@
;; arithmetic shift right
(define_insn "ashrqi3"
- [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,r ,r ,r")
- (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0 ,0 ,0")
- (match_operand:QI 2 "general_operand" "r,L,P,K,C03 C04 C05,C06 C07,Qm")))]
+ [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,r ,r ,r")
+ (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0 ,0 ,0")
+ (match_operand:QI 2 "nop_general_operand" "r,L,P,K,C03 C04 C05,C06 C07,Qm")))]
""
- "* return ashrqi3_out (insn, operands, NULL);"
+ {
+ return ashrqi3_out (insn, operands, NULL);
+ }
[(set_attr "length" "5,0,1,2,5,4,9")
(set_attr "adjust_len" "ashrqi")
(set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,clobber,clobber")])
(define_insn "ashrhi3"
- [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r,r")
- (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0,0,r,0,0,0")
- (match_operand:QI 2 "general_operand" "r,L,P,O,K,n,Qm")))]
+ [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r,r")
+ (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0,0,r,0,0,0")
+ (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))]
""
- "* return ashrhi3_out (insn, operands, NULL);"
+ {
+ return ashrhi3_out (insn, operands, NULL);
+ }
[(set_attr "length" "6,0,2,4,4,10,10")
(set_attr "adjust_len" "ashrhi")
(set_attr "cc" "clobber,none,clobber,set_n,clobber,clobber,clobber")])
@@ -3141,11 +3415,13 @@
(set_attr "cc" "clobber")])
(define_insn "ashrsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r")
- (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
- (match_operand:QI 2 "general_operand" "r,L,P,O,K,n,Qm")))]
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
+ (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))]
""
- "* return ashrsi3_out (insn, operands, NULL);"
+ {
+ return ashrsi3_out (insn, operands, NULL);
+ }
[(set_attr "length" "8,0,4,6,8,10,12")
(set_attr "adjust_len" "ashrsi")
(set_attr "cc" "clobber,none,clobber,set_n,clobber,clobber,clobber")])
@@ -3164,11 +3440,13 @@
(define_insn "*ashrhi3_const"
[(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r")
- (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0,r,0,0")
- (match_operand:QI 2 "const_int_operand" "L,P,O,K,n")))
- (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))]
+ (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0,r,0,0")
+ (match_operand:QI 2 "const_int_operand" "L,P,O,K,n")))
+ (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))]
"reload_completed"
- "* return ashrhi3_out (insn, operands, NULL);"
+ {
+ return ashrhi3_out (insn, operands, NULL);
+ }
[(set_attr "length" "0,2,4,4,10")
(set_attr "adjust_len" "ashrhi")
(set_attr "cc" "none,clobber,set_n,clobber,clobber")])
@@ -3185,11 +3463,13 @@
(define_insn "*ashrsi3_const"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r,0")
- (match_operand:QI 2 "const_int_operand" "L,P,O,n")))
- (clobber (match_scratch:QI 3 "=X,X,X,&d"))]
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r,0")
+ (match_operand:QI 2 "const_int_operand" "L,P,O,n")))
+ (clobber (match_scratch:QI 3 "=X,X,X,&d"))]
"reload_completed"
- "* return ashrsi3_out (insn, operands, NULL);"
+ {
+ return ashrsi3_out (insn, operands, NULL);
+ }
[(set_attr "length" "0,4,4,10")
(set_attr "adjust_len" "ashrsi")
(set_attr "cc" "none,clobber,set_n,clobber")])
@@ -3198,11 +3478,9 @@
;; logical shift right
(define_expand "lshrqi3"
- [(set (match_operand:QI 0 "register_operand" "")
- (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
- (match_operand:QI 2 "general_operand" "")))]
- ""
- "")
+ [(set (match_operand:QI 0 "register_operand" "")
+ (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
+ (match_operand:QI 2 "nop_general_operand" "")))])
(define_split ; lshrqi3_const4
[(set (match_operand:QI 0 "d_register_operand" "")
@@ -3234,21 +3512,25 @@
"")
(define_insn "*lshrqi3"
- [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,!d,r,r")
- (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0,0,0")
- (match_operand:QI 2 "general_operand" "r,L,P,K,n,n,Qm")))]
+ [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,!d,r,r")
+ (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0 ,0,0")
+ (match_operand:QI 2 "nop_general_operand" "r,L,P,K,n ,n,Qm")))]
""
- "* return lshrqi3_out (insn, operands, NULL);"
+ {
+ return lshrqi3_out (insn, operands, NULL);
+ }
[(set_attr "length" "5,0,1,2,4,6,9")
(set_attr "adjust_len" "lshrqi")
(set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,set_czn,clobber")])
(define_insn "lshrhi3"
- [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r,r")
- (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0,0,r,0,0,0")
- (match_operand:QI 2 "general_operand" "r,L,P,O,K,n,Qm")))]
+ [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r,r")
+ (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0,0,r,0,0,0")
+ (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))]
""
- "* return lshrhi3_out (insn, operands, NULL);"
+ {
+ return lshrhi3_out (insn, operands, NULL);
+ }
[(set_attr "length" "6,0,2,2,4,10,10")
(set_attr "adjust_len" "lshrhi")
(set_attr "cc" "clobber,none,clobber,clobber,clobber,clobber,clobber")])
@@ -3266,11 +3548,13 @@
(set_attr "cc" "clobber")])
(define_insn "lshrsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r")
- (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
- (match_operand:QI 2 "general_operand" "r,L,P,O,K,n,Qm")))]
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
+ (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))]
""
- "* return lshrsi3_out (insn, operands, NULL);"
+ {
+ return lshrsi3_out (insn, operands, NULL);
+ }
[(set_attr "length" "8,0,4,4,8,10,12")
(set_attr "adjust_len" "lshrsi")
(set_attr "cc" "clobber,none,clobber,clobber,clobber,clobber,clobber")])
@@ -3324,11 +3608,13 @@
(define_insn "*lshrhi3_const"
[(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r")
- (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0,r,0,0")
- (match_operand:QI 2 "const_int_operand" "L,P,O,K,n")))
- (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))]
+ (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0,r,0,0")
+ (match_operand:QI 2 "const_int_operand" "L,P,O,K,n")))
+ (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))]
"reload_completed"
- "* return lshrhi3_out (insn, operands, NULL);"
+ {
+ return lshrhi3_out (insn, operands, NULL);
+ }
[(set_attr "length" "0,2,2,4,10")
(set_attr "adjust_len" "lshrhi")
(set_attr "cc" "none,clobber,clobber,clobber,clobber")])
@@ -3345,11 +3631,13 @@
(define_insn "*lshrsi3_const"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r,0")
- (match_operand:QI 2 "const_int_operand" "L,P,O,n")))
- (clobber (match_scratch:QI 3 "=X,X,X,&d"))]
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r,0")
+ (match_operand:QI 2 "const_int_operand" "L,P,O,n")))
+ (clobber (match_scratch:QI 3 "=X,X,X,&d"))]
"reload_completed"
- "* return lshrsi3_out (insn, operands, NULL);"
+ {
+ return lshrsi3_out (insn, operands, NULL);
+ }
[(set_attr "length" "0,4,4,10")
(set_attr "adjust_len" "lshrsi")
(set_attr "cc" "none,clobber,clobber,clobber")])
@@ -3615,6 +3903,27 @@
operands[3] = simplify_gen_subreg (QImode, operands[0], PSImode, 2);
})
+(define_insn_and_split "n_extendhipsi2"
+ [(set (match_operand:PSI 0 "register_operand" "=r,r,d,r")
+ (lo_sum:PSI (match_operand:QI 1 "const_int_operand" "L,P,n,n")
+ (match_operand:HI 2 "register_operand" "r,r,r,r")))
+ (clobber (match_scratch:QI 3 "=X,X,X,&d"))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 4) (match_dup 2))
+ (set (match_dup 3) (match_dup 6))
+ ; no-op move in the case where no scratch is needed
+ (set (match_dup 5) (match_dup 3))]
+ {
+ operands[4] = simplify_gen_subreg (HImode, operands[0], PSImode, 0);
+ operands[5] = simplify_gen_subreg (QImode, operands[0], PSImode, 2);
+ operands[6] = operands[1];
+
+ if (GET_CODE (operands[3]) == SCRATCH)
+ operands[3] = operands[5];
+ })
+
(define_insn_and_split "zero_extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(zero_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "r")))]
@@ -4363,25 +4672,25 @@
(define_insn "*cbi"
[(set (mem:QI (match_operand 0 "low_io_address_operand" "n"))
- (and:QI (mem:QI (match_dup 0))
- (match_operand:QI 1 "single_zero_operand" "n")))]
- "(optimize > 0)"
-{
- operands[2] = GEN_INT (exact_log2 (~INTVAL (operands[1]) & 0xff));
- return AS2 (cbi,%m0-0x20,%2);
-}
+ (and:QI (mem:QI (match_dup 0))
+ (match_operand:QI 1 "single_zero_operand" "n")))]
+ "optimize > 0"
+ {
+ operands[2] = GEN_INT (exact_log2 (~INTVAL (operands[1]) & 0xff));
+ return "cbi %i0,%2";
+ }
[(set_attr "length" "1")
(set_attr "cc" "none")])
(define_insn "*sbi"
[(set (mem:QI (match_operand 0 "low_io_address_operand" "n"))
- (ior:QI (mem:QI (match_dup 0))
- (match_operand:QI 1 "single_one_operand" "n")))]
- "(optimize > 0)"
-{
- operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1]) & 0xff));
- return AS2 (sbi,%m0-0x20,%2);
-}
+ (ior:QI (mem:QI (match_dup 0))
+ (match_operand:QI 1 "single_one_operand" "n")))]
+ "optimize > 0"
+ {
+ operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1]) & 0xff));
+ return "sbi %i0,%2";
+ }
[(set_attr "length" "1")
(set_attr "cc" "none")])
@@ -4796,6 +5105,30 @@
[(set_attr "length" "9")
(set_attr "cc" "clobber")])
+(define_insn "map_bitsqi"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (unspec:QI [(match_operand:SI 1 "const_int_operand" "n")
+ (match_operand:QI 2 "register_operand" "r")]
+ UNSPEC_MAP_BITS))]
+ ""
+ {
+ return avr_out_map_bits (insn, operands, NULL);
+ }
+ [(set_attr "adjust_len" "map_bits")
+ (set_attr "cc" "clobber")])
+
+(define_insn "map_bitshi"
+ [(set (match_operand:HI 0 "register_operand" "=&r")
+ (unspec:HI [(match_operand:DI 1 "const_double_operand" "n")
+ (match_operand:HI 2 "register_operand" "r")]
+ UNSPEC_MAP_BITS))]
+ ""
+ {
+ return avr_out_map_bits (insn, operands, NULL);
+ }
+ [(set_attr "adjust_len" "map_bits")
+ (set_attr "cc" "clobber")])
+
;; Parity
@@ -5340,9 +5673,9 @@
(match_operand:QI 2 "nonmemory_operand" "L,P,r"))]
""
"@
- cbi %m0-0x20,%1
- sbi %m0-0x20,%1
- sbrc %2,0\;sbi %m0-0x20,%1\;sbrs %2,0\;cbi %m0-0x20,%1"
+ cbi %i0,%1
+ sbi %i0,%1
+ sbrc %2,0\;sbi %i0,%1\;sbrs %2,0\;cbi %i0,%1"
[(set_attr "length" "1,1,4")
(set_attr "cc" "none")])
@@ -5352,7 +5685,7 @@
(match_operand:QI 1 "const_0_to_7_operand" "n"))
(not:QI (match_operand:QI 2 "register_operand" "r")))]
""
- "sbrs %2,0\;sbi %m0-0x20,%1\;sbrc %2,0\;cbi %m0-0x20,%1"
+ "sbrs %2,0\;sbi %i0,%1\;sbrc %2,0\;cbi %i0,%1"
[(set_attr "length" "4")
(set_attr "cc" "none")])
diff --git a/gcc/config/avr/predicates.md b/gcc/config/avr/predicates.md
index 55a25b8b05a..fff34b58464 100644
--- a/gcc/config/avr/predicates.md
+++ b/gcc/config/avr/predicates.md
@@ -57,6 +57,18 @@
(and (match_code "const_int")
(match_test "IN_RANGE((INTVAL (op)), 0x20, (0x60 - GET_MODE_SIZE(mode)))")))
+;; Return 1 if OP is a general operand not in program memory
+(define_predicate "nop_general_operand"
+ (and (match_operand 0 "general_operand")
+ (match_test "!avr_mem_pgm_p (op)")))
+
+;; Return 1 if OP is an "ordinary" general operand, i.e. a general
+;; operand whose load is not handled by a libgcc call or ELPM.
+(define_predicate "nox_general_operand"
+ (and (match_operand 0 "general_operand")
+ (not (match_test "avr_load_libgcc_p (op)"))
+ (not (match_test "avr_mem_pgmx_p (op)"))))
+
;; Return 1 if OP is the zero constant for MODE.
(define_predicate "const0_operand"
(and (match_code "const_int,const_double")
diff --git a/gcc/config/cris/cris-protos.h b/gcc/config/cris/cris-protos.h
index 291981d5707..545f821ac0f 100644
--- a/gcc/config/cris/cris-protos.h
+++ b/gcc/config/cris/cris-protos.h
@@ -65,5 +65,3 @@ extern int cris_fatal (char *);
extern int cris_initial_elimination_offset (int, int);
extern void cris_init_expanders (void);
-
-extern bool cris_function_value_regno_p (const unsigned int);
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index 06568023051..de9e26984ea 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -153,6 +153,7 @@ static void cris_trampoline_init (rtx, tree, rtx);
static rtx cris_function_value(const_tree, const_tree, bool);
static rtx cris_libcall_value (enum machine_mode, const_rtx);
+static bool cris_function_value_regno_p (const unsigned int);
/* This is the parsed result of the "-max-stack-stackframe=" option. If
it (still) is zero, then there was no such option given. */
@@ -252,6 +253,8 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;
#define TARGET_FUNCTION_VALUE cris_function_value
#undef TARGET_LIBCALL_VALUE
#define TARGET_LIBCALL_VALUE cris_libcall_value
+#undef TARGET_FUNCTION_VALUE_REGNO_P
+#define TARGET_FUNCTION_VALUE_REGNO_P cris_function_value_regno_p
struct gcc_target targetm = TARGET_INITIALIZER;
@@ -3931,7 +3934,7 @@ cris_libcall_value (enum machine_mode mode,
/* Let's assume all functions return in r[CRIS_FIRST_ARG_REG] for the
time being. */
-bool
+static bool
cris_function_value_regno_p (const unsigned int regno)
{
return (regno == CRIS_FIRST_ARG_REG);
diff --git a/gcc/config/cris/cris.h b/gcc/config/cris/cris.h
index 5a6ebda2e48..ff0be0041f0 100644
--- a/gcc/config/cris/cris.h
+++ b/gcc/config/cris/cris.h
@@ -712,12 +712,6 @@ struct cum_args {int regs;};
&& (REGNO) < CRIS_FIRST_ARG_REG + (CRIS_MAX_ARGS_IN_REGS))
-/* Node: Scalar Return */
-
-#define FUNCTION_VALUE_REGNO_P(N) cris_function_value_regno_p (N)
-
-
-
/* Node: Aggregate Return */
#define CRIS_STRUCT_VALUE_REGNUM ((CRIS_FIRST_ARG_REG) - 1)
diff --git a/gcc/config/darwin-protos.h b/gcc/config/darwin-protos.h
index 21092af66e2..e0220864fac 100644
--- a/gcc/config/darwin-protos.h
+++ b/gcc/config/darwin-protos.h
@@ -58,6 +58,7 @@ extern int machopic_reloc_rw_mask (void);
extern section *machopic_select_section (tree, int, unsigned HOST_WIDE_INT);
extern section *darwin_function_section (tree, enum node_frequency, bool, bool);
+extern section *darwin_tm_clone_table_section (void);
extern void darwin_function_switched_text_sections (FILE *, tree, bool);
extern void darwin_unique_section (tree decl, int reloc);
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index 7c33a533fff..b1038f40660 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -1265,6 +1265,14 @@ darwin_mergeable_constant_section (tree exp,
return readonly_data_section;
}
+section *
+darwin_tm_clone_table_section (void)
+{
+ return get_named_section (NULL,
+ "__DATA,__tm_clone_table,regular,no_dead_strip",
+ 3);
+}
+
int
machopic_reloc_rw_mask (void)
{
diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
index 0c8f2769abe..29a24ddc6d6 100644
--- a/gcc/config/darwin.h
+++ b/gcc/config/darwin.h
@@ -359,8 +359,8 @@ extern GTY(()) int darwin_ms_struct;
#undef STARTFILE_SPEC
#define STARTFILE_SPEC \
- "%{Zdynamiclib: %(darwin_dylib1) } \
- %{!Zdynamiclib:%{Zbundle:%{!static:-lbundle1.o}} \
+ "%{Zdynamiclib: %(darwin_dylib1) %{fgnu-tm: -lcrttms.o}} \
+ %{!Zdynamiclib:%{Zbundle:%{!static:-lbundle1.o %{fgnu-tm: -lcrttms.o}}} \
%{!Zbundle:%{pg:%{static:-lgcrt0.o} \
%{!static:%{object:-lgcrt0.o} \
%{!object:%{preload:-lgcrt0.o} \
@@ -372,10 +372,8 @@ extern GTY(()) int darwin_ms_struct;
%(darwin_crt2)}}}}}} \
%{shared-libgcc:%:version-compare(< 10.5 mmacosx-version-min= crt3.o%s)}"
-/* The native Darwin linker doesn't necessarily place files in the order
- that they're specified on the link line. Thus, it is pointless
- to put anything in ENDFILE_SPEC. */
-/* #define ENDFILE_SPEC "" */
+/* We want a destructor last in the list. */
+#define ENDFILE_SPEC "%{fgnu-tm: -lcrttme.o}"
#define DARWIN_EXTRA_SPECS \
{ "darwin_crt1", DARWIN_CRT1_SPEC }, \
@@ -388,13 +386,19 @@ extern GTY(()) int darwin_ms_struct;
#define DARWIN_CRT1_SPEC \
"%:version-compare(!> 10.5 mmacosx-version-min= -lcrt1.o) \
- %:version-compare(>= 10.5 mmacosx-version-min= -lcrt1.10.5.o)"
+ %:version-compare(>= 10.5 mmacosx-version-min= -lcrt1.10.5.o) \
+ %{fgnu-tm: -lcrttms.o}"
/* Default Darwin ASM_SPEC, very simple. */
#define ASM_SPEC "-arch %(darwin_arch) \
%{Zforce_cpusubtype_ALL:-force_cpusubtype_ALL} \
%{static}"
+/* Default ASM_DEBUG_SPEC. Darwin's as cannot currently produce dwarf
+ debugging data. */
+
+#define ASM_DEBUG_SPEC "%{g*:%{!g0:%{!gdwarf*:--gstabs}}}"
+
/* We still allow output of STABS. */
#define DBX_DEBUGGING_INFO 1
@@ -692,6 +696,10 @@ extern GTY(()) section * darwin_sections[NUM_DARWIN_SECTIONS];
#define TARGET_ASM_UNIQUE_SECTION darwin_unique_section
#undef TARGET_ASM_FUNCTION_RODATA_SECTION
#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
+
+#undef TARGET_ASM_TM_CLONE_TABLE_SECTION
+#define TARGET_ASM_TM_CLONE_TABLE_SECTION darwin_tm_clone_table_section
+
#undef TARGET_ASM_RELOC_RW_MASK
#define TARGET_ASM_RELOC_RW_MASK machopic_reloc_rw_mask
diff --git a/gcc/config/darwin9.h b/gcc/config/darwin9.h
index 483a7e5269c..92429cae57c 100644
--- a/gcc/config/darwin9.h
+++ b/gcc/config/darwin9.h
@@ -41,6 +41,12 @@ along with GCC; see the file COPYING3. If not see
%{mdynamic-no-pic: %n'-mdynamic-no-pic' overrides '-pie', '-fpie' or '-fPIE'; \
:-pie}}"
+/* Only ask as for debug data if the debug style is stabs (since as doesn't
+ yet generate dwarf.) */
+
+#undef ASM_DEBUG_SPEC
+#define ASM_DEBUG_SPEC "%{g*:%{!g0:%{gstabs:--gstabs}}}"
+
#undef ASM_OUTPUT_ALIGNED_COMMON
#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
do { \
diff --git a/gcc/config/epiphany/epiphany.md b/gcc/config/epiphany/epiphany.md
index c8354e8eddb..7f8f2a95231 100644
--- a/gcc/config/epiphany/epiphany.md
+++ b/gcc/config/epiphany/epiphany.md
@@ -1711,7 +1711,7 @@
cmp_in_mode = GET_MODE (cmp_op0);
if (cmp_in_mode == VOIDmode)
- cmp_in_mode = GET_MODE (cmp_op0);
+ cmp_in_mode = GET_MODE (cmp_op1);
if (cmp_in_mode == VOIDmode)
cmp_in_mode = SImode;
/* If the operands are a better match when reversed, swap them now.
diff --git a/gcc/config/host-linux.c b/gcc/config/host-linux.c
index ec6105577a6..94b7a0b89a7 100644
--- a/gcc/config/host-linux.c
+++ b/gcc/config/host-linux.c
@@ -86,6 +86,10 @@
# define TRY_EMPTY_VM_SPACE 0x40000000
#elif defined(__ARM_EABI__)
# define TRY_EMPTY_VM_SPACE 0x60000000
+#elif defined(__mips__) && defined(__LP64__)
+# define TRY_EMPTY_VM_SPACE 0x8000000000
+#elif defined(__mips__)
+# define TRY_EMPTY_VM_SPACE 0x60000000
#else
# define TRY_EMPTY_VM_SPACE 0
#endif
diff --git a/gcc/config/i386/darwin.h b/gcc/config/i386/darwin.h
index 705fe98c613..83da2932512 100644
--- a/gcc/config/i386/darwin.h
+++ b/gcc/config/i386/darwin.h
@@ -132,7 +132,8 @@ extern int darwin_emit_branch_islands;
"%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \
%{mpc32:crtprec32.o%s} \
%{mpc64:crtprec64.o%s} \
- %{mpc80:crtprec80.o%s}"
+ %{mpc80:crtprec80.o%s} \
+ %{fgnu-tm: -lcrttme.o}"
#undef SUBTARGET_EXTRA_SPECS
#define SUBTARGET_EXTRA_SPECS \
diff --git a/gcc/config/i386/emmintrin.h b/gcc/config/i386/emmintrin.h
index fe4cd6abaea..07ac9f3d8ae 100644
--- a/gcc/config/i386/emmintrin.h
+++ b/gcc/config/i386/emmintrin.h
@@ -1418,6 +1418,14 @@ _mm_stream_si32 (int *__A, int __B)
__builtin_ia32_movnti (__A, __B);
}
+#ifdef __x86_64__
+extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_stream_si64 (long long int *__A, long long int __B)
+{
+ __builtin_ia32_movnti64 (__A, __B);
+}
+#endif
+
extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_stream_si128 (__m128i *__A, __m128i __B)
{
diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def
index 5dcb68c2d43..d00b05341b9 100644
--- a/gcc/config/i386/i386-builtin-types.def
+++ b/gcc/config/i386/i386-builtin-types.def
@@ -111,6 +111,7 @@ DEF_POINTER_TYPE (PDOUBLE, DOUBLE)
DEF_POINTER_TYPE (PFLOAT, FLOAT)
DEF_POINTER_TYPE (PUSHORT, USHORT)
DEF_POINTER_TYPE (PINT, INT)
+DEF_POINTER_TYPE (PLONGLONG, LONGLONG)
DEF_POINTER_TYPE (PULONGLONG, ULONGLONG)
DEF_POINTER_TYPE (PUNSIGNED, UNSIGNED)
@@ -357,6 +358,7 @@ DEF_FUNCTION_TYPE (VOID, PDOUBLE, V4DF)
DEF_FUNCTION_TYPE (VOID, PFLOAT, V4SF)
DEF_FUNCTION_TYPE (VOID, PFLOAT, V8SF)
DEF_FUNCTION_TYPE (VOID, PINT, INT)
+DEF_FUNCTION_TYPE (VOID, PLONGLONG, LONGLONG)
DEF_FUNCTION_TYPE (VOID, PULONGLONG, ULONGLONG)
DEF_FUNCTION_TYPE (VOID, PV2SI, V2SI)
DEF_FUNCTION_TYPE (VOID, PV2DI, V2DI)
@@ -465,6 +467,11 @@ DEF_FUNCTION_TYPE_ALIAS (V4DF_FTYPE_V4DF, ROUND)
DEF_FUNCTION_TYPE_ALIAS (V4SF_FTYPE_V4SF, ROUND)
DEF_FUNCTION_TYPE_ALIAS (V8SF_FTYPE_V8SF, ROUND)
+DEF_FUNCTION_TYPE_ALIAS (V4SI_FTYPE_V2DF_V2DF, ROUND)
+DEF_FUNCTION_TYPE_ALIAS (V8SI_FTYPE_V4DF_V4DF, ROUND)
+DEF_FUNCTION_TYPE_ALIAS (V4SI_FTYPE_V4SF, ROUND)
+DEF_FUNCTION_TYPE_ALIAS (V8SI_FTYPE_V8SF, ROUND)
+
DEF_FUNCTION_TYPE_ALIAS (INT_FTYPE_V2DF_V2DF, PTEST)
DEF_FUNCTION_TYPE_ALIAS (INT_FTYPE_V2DI_V2DI, PTEST)
DEF_FUNCTION_TYPE_ALIAS (INT_FTYPE_V4DF_V4DF, PTEST)
diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
index 07f58b99e35..3cc2253c3c2 100644
--- a/gcc/config/i386/i386-opts.h
+++ b/gcc/config/i386/i386-opts.h
@@ -37,8 +37,7 @@ enum stringop_alg
rep_prefix_8_byte,
loop_1_byte,
loop,
- unrolled_loop,
- sse_loop
+ unrolled_loop
};
/* Available call abi. */
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index a8e8a6a40e1..1b871be8480 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -561,14 +561,10 @@ struct processor_costs ix86_size_cost = {/* costs for tuning for size */
COSTS_N_BYTES (2), /* cost of FABS instruction. */
COSTS_N_BYTES (2), /* cost of FCHS instruction. */
COSTS_N_BYTES (2), /* cost of FSQRT instruction. */
- {{{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
+ {{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}}},
- {{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
- {rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}}}},
- {{{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
+ {{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}}},
- {{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
- {rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}}}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -636,14 +632,10 @@ struct processor_costs i386_cost = { /* 386 specific costs */
COSTS_N_INSNS (22), /* cost of FABS instruction. */
COSTS_N_INSNS (24), /* cost of FCHS instruction. */
COSTS_N_INSNS (122), /* cost of FSQRT instruction. */
- {{{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
+ {{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
DUMMY_STRINGOP_ALGS},
- {{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
- DUMMY_STRINGOP_ALGS}},
- {{{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
+ {{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
DUMMY_STRINGOP_ALGS},
- {{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
- DUMMY_STRINGOP_ALGS}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -712,14 +704,10 @@ struct processor_costs i486_cost = { /* 486 specific costs */
COSTS_N_INSNS (3), /* cost of FABS instruction. */
COSTS_N_INSNS (3), /* cost of FCHS instruction. */
COSTS_N_INSNS (83), /* cost of FSQRT instruction. */
- {{{rep_prefix_4_byte, {{-1, rep_prefix_4_byte}}},
+ {{rep_prefix_4_byte, {{-1, rep_prefix_4_byte}}},
DUMMY_STRINGOP_ALGS},
- {{rep_prefix_4_byte, {{-1, rep_prefix_4_byte}}},
- DUMMY_STRINGOP_ALGS}},
- {{{rep_prefix_4_byte, {{-1, rep_prefix_4_byte}}},
+ {{rep_prefix_4_byte, {{-1, rep_prefix_4_byte}}},
DUMMY_STRINGOP_ALGS},
- {{rep_prefix_4_byte, {{-1, rep_prefix_4_byte}}},
- DUMMY_STRINGOP_ALGS}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -786,14 +774,10 @@ struct processor_costs pentium_cost = {
COSTS_N_INSNS (1), /* cost of FABS instruction. */
COSTS_N_INSNS (1), /* cost of FCHS instruction. */
COSTS_N_INSNS (70), /* cost of FSQRT instruction. */
- {{{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
+ {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
- {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
- DUMMY_STRINGOP_ALGS}},
- {{{libcall, {{-1, rep_prefix_4_byte}}},
+ {{libcall, {{-1, rep_prefix_4_byte}}},
DUMMY_STRINGOP_ALGS},
- {{libcall, {{-1, rep_prefix_4_byte}}},
- DUMMY_STRINGOP_ALGS}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -865,18 +849,12 @@ struct processor_costs pentiumpro_cost = {
noticeable win, for bigger blocks either rep movsl or rep movsb is
way to go. Rep movsb has apparently more expensive startup time in CPU,
but after 4K the difference is down in the noise. */
- {{{rep_prefix_4_byte, {{128, loop}, {1024, unrolled_loop},
+ {{rep_prefix_4_byte, {{128, loop}, {1024, unrolled_loop},
{8192, rep_prefix_4_byte}, {-1, rep_prefix_1_byte}}},
DUMMY_STRINGOP_ALGS},
- {{rep_prefix_4_byte, {{128, loop}, {1024, unrolled_loop},
- {8192, rep_prefix_4_byte}, {-1, rep_prefix_1_byte}}},
- DUMMY_STRINGOP_ALGS}},
- {{{rep_prefix_4_byte, {{1024, unrolled_loop},
- {8192, rep_prefix_4_byte}, {-1, libcall}}},
+ {{rep_prefix_4_byte, {{1024, unrolled_loop},
+ {8192, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
- {{rep_prefix_4_byte, {{1024, unrolled_loop},
- {8192, rep_prefix_4_byte}, {-1, libcall}}},
- DUMMY_STRINGOP_ALGS}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -944,14 +922,10 @@ struct processor_costs geode_cost = {
COSTS_N_INSNS (1), /* cost of FABS instruction. */
COSTS_N_INSNS (1), /* cost of FCHS instruction. */
COSTS_N_INSNS (54), /* cost of FSQRT instruction. */
- {{{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
+ {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
- {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
- DUMMY_STRINGOP_ALGS}},
- {{{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
+ {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
- {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
- DUMMY_STRINGOP_ALGS}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -1021,14 +995,10 @@ struct processor_costs k6_cost = {
COSTS_N_INSNS (2), /* cost of FABS instruction. */
COSTS_N_INSNS (2), /* cost of FCHS instruction. */
COSTS_N_INSNS (56), /* cost of FSQRT instruction. */
- {{{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
+ {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
- {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
- DUMMY_STRINGOP_ALGS}},
- {{{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
+ {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
- {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
- DUMMY_STRINGOP_ALGS}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -1098,14 +1068,10 @@ struct processor_costs athlon_cost = {
/* For some reason, Athlon deals better with REP prefix (relative to loops)
compared to K8. Alignment becomes important after 8 bytes for memcpy and
128 bytes for memset. */
- {{{libcall, {{2048, rep_prefix_4_byte}, {-1, libcall}}},
+ {{libcall, {{2048, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
- {{libcall, {{2048, rep_prefix_4_byte}, {-1, libcall}}},
- DUMMY_STRINGOP_ALGS}},
- {{{libcall, {{2048, rep_prefix_4_byte}, {-1, libcall}}},
+ {{libcall, {{2048, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
- {{libcall, {{2048, rep_prefix_4_byte}, {-1, libcall}}},
- DUMMY_STRINGOP_ALGS}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -1180,16 +1146,11 @@ struct processor_costs k8_cost = {
/* K8 has optimized REP instruction for medium sized blocks, but for very
small blocks it is better to use loop. For large blocks, libcall can
do nontemporary accesses and beat inline considerably. */
- {{{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
+ {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
{libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
- {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
- {libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
- {{{libcall, {{8, loop}, {24, unrolled_loop},
+ {{libcall, {{8, loop}, {24, unrolled_loop},
{2048, rep_prefix_4_byte}, {-1, libcall}}},
{libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
- {{libcall, {{8, loop}, {24, unrolled_loop},
- {2048, rep_prefix_4_byte}, {-1, libcall}}},
- {libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
4, /* scalar_stmt_cost. */
2, /* scalar load_cost. */
2, /* scalar_store_cost. */
@@ -1272,16 +1233,11 @@ struct processor_costs amdfam10_cost = {
/* AMDFAM10 has optimized REP instruction for medium sized blocks, but for
very small blocks it is better to use loop. For large blocks, libcall can
do nontemporary accesses and beat inline considerably. */
- {{{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
- {libcall, {{16, loop}, {512, rep_prefix_8_byte}, {-1, libcall}}}},
- {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
- {libcall, {{16, loop}, {512, rep_prefix_8_byte}, {-1, libcall}}}}},
- {{{libcall, {{8, loop}, {24, unrolled_loop},
+ {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
+ {libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
+ {{libcall, {{8, loop}, {24, unrolled_loop},
{2048, rep_prefix_4_byte}, {-1, libcall}}},
{libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
- {{libcall, {{8, loop}, {24, unrolled_loop},
- {2048, rep_prefix_4_byte}, {-1, libcall}}},
- {libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
4, /* scalar_stmt_cost. */
2, /* scalar load_cost. */
2, /* scalar_store_cost. */
@@ -1364,16 +1320,11 @@ struct processor_costs bdver1_cost = {
/* BDVER1 has optimized REP instruction for medium sized blocks, but for
very small blocks it is better to use loop. For large blocks, libcall
can do nontemporary accesses and beat inline considerably. */
- {{{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
+ {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
{libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
- {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
- {libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
- {{{libcall, {{8, loop}, {24, unrolled_loop},
+ {{libcall, {{8, loop}, {24, unrolled_loop},
{2048, rep_prefix_4_byte}, {-1, libcall}}},
{libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
- {{libcall, {{8, loop}, {24, unrolled_loop},
- {2048, rep_prefix_4_byte}, {-1, libcall}}},
- {libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
6, /* scalar_stmt_cost. */
4, /* scalar load_cost. */
4, /* scalar_store_cost. */
@@ -1456,16 +1407,11 @@ struct processor_costs bdver2_cost = {
/* BDVER2 has optimized REP instruction for medium sized blocks, but for
very small blocks it is better to use loop. For large blocks, libcall
can do nontemporary accesses and beat inline considerably. */
- {{{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
- {libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
{{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
- {libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
- {{{libcall, {{8, loop}, {24, unrolled_loop},
- {2048, rep_prefix_4_byte}, {-1, libcall}}},
- {libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
+ {libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
{{libcall, {{8, loop}, {24, unrolled_loop},
{2048, rep_prefix_4_byte}, {-1, libcall}}},
- {libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
+ {libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
6, /* scalar_stmt_cost. */
4, /* scalar load_cost. */
4, /* scalar_store_cost. */
@@ -1543,16 +1489,11 @@ struct processor_costs btver1_cost = {
/* BTVER1 has optimized REP instruction for medium sized blocks, but for
very small blocks it is better to use loop. For large blocks, libcall can
do nontemporary accesses and beat inline considerably. */
- {{{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
+ {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
{libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
- {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
- {libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
- {{{libcall, {{8, loop}, {24, unrolled_loop},
+ {{libcall, {{8, loop}, {24, unrolled_loop},
{2048, rep_prefix_4_byte}, {-1, libcall}}},
{libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
- {{libcall, {{8, loop}, {24, unrolled_loop},
- {2048, rep_prefix_4_byte}, {-1, libcall}}},
- {libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
4, /* scalar_stmt_cost. */
2, /* scalar load_cost. */
2, /* scalar_store_cost. */
@@ -1619,18 +1560,11 @@ struct processor_costs pentium4_cost = {
COSTS_N_INSNS (2), /* cost of FABS instruction. */
COSTS_N_INSNS (2), /* cost of FCHS instruction. */
COSTS_N_INSNS (43), /* cost of FSQRT instruction. */
-
- {{{libcall, {{12, loop_1_byte}, {-1, rep_prefix_4_byte}}},
+ {{libcall, {{12, loop_1_byte}, {-1, rep_prefix_4_byte}}},
DUMMY_STRINGOP_ALGS},
- {{libcall, {{12, loop_1_byte}, {-1, rep_prefix_4_byte}}},
- DUMMY_STRINGOP_ALGS}},
-
- {{{libcall, {{6, loop_1_byte}, {48, loop}, {20480, rep_prefix_4_byte},
+ {{libcall, {{6, loop_1_byte}, {48, loop}, {20480, rep_prefix_4_byte},
{-1, libcall}}},
DUMMY_STRINGOP_ALGS},
- {{libcall, {{6, loop_1_byte}, {48, loop}, {20480, rep_prefix_4_byte},
- {-1, libcall}}},
- DUMMY_STRINGOP_ALGS}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -1697,22 +1631,13 @@ struct processor_costs nocona_cost = {
COSTS_N_INSNS (3), /* cost of FABS instruction. */
COSTS_N_INSNS (3), /* cost of FCHS instruction. */
COSTS_N_INSNS (44), /* cost of FSQRT instruction. */
-
- {{{libcall, {{12, loop_1_byte}, {-1, rep_prefix_4_byte}}},
+ {{libcall, {{12, loop_1_byte}, {-1, rep_prefix_4_byte}}},
{libcall, {{32, loop}, {20000, rep_prefix_8_byte},
{100000, unrolled_loop}, {-1, libcall}}}},
- {{libcall, {{12, loop_1_byte}, {-1, rep_prefix_4_byte}}},
- {libcall, {{32, loop}, {20000, rep_prefix_8_byte},
- {100000, unrolled_loop}, {-1, libcall}}}}},
-
- {{{libcall, {{6, loop_1_byte}, {48, loop}, {20480, rep_prefix_4_byte},
+ {{libcall, {{6, loop_1_byte}, {48, loop}, {20480, rep_prefix_4_byte},
{-1, libcall}}},
{libcall, {{24, loop}, {64, unrolled_loop},
{8192, rep_prefix_8_byte}, {-1, libcall}}}},
- {{libcall, {{6, loop_1_byte}, {48, loop}, {20480, rep_prefix_4_byte},
- {-1, libcall}}},
- {libcall, {{24, loop}, {64, unrolled_loop},
- {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -1779,108 +1704,13 @@ struct processor_costs atom_cost = {
COSTS_N_INSNS (8), /* cost of FABS instruction. */
COSTS_N_INSNS (8), /* cost of FCHS instruction. */
COSTS_N_INSNS (40), /* cost of FSQRT instruction. */
-
- /* stringop_algs for memcpy.
- SSE loops works best on Atom, but fall back into non-SSE unrolled loop variant
- if that fails. */
- {{{libcall, {{4096, sse_loop}, {4096, unrolled_loop}, {-1, libcall}}}, /* Known alignment. */
- {libcall, {{4096, sse_loop}, {4096, unrolled_loop}, {-1, libcall}}}},
- {{libcall, {{-1, libcall}}}, /* Unknown alignment. */
- {libcall, {{2048, sse_loop}, {2048, unrolled_loop},
- {-1, libcall}}}}},
-
- /* stringop_algs for memset. */
- {{{libcall, {{4096, sse_loop}, {4096, unrolled_loop}, {-1, libcall}}}, /* Known alignment. */
- {libcall, {{4096, sse_loop}, {4096, unrolled_loop}, {-1, libcall}}}},
- {{libcall, {{1024, sse_loop}, {1024, unrolled_loop}, /* Unknown alignment. */
- {-1, libcall}}},
- {libcall, {{2048, sse_loop}, {2048, unrolled_loop},
- {-1, libcall}}}}},
- 1, /* scalar_stmt_cost. */
- 1, /* scalar load_cost. */
- 1, /* scalar_store_cost. */
- 1, /* vec_stmt_cost. */
- 1, /* vec_to_scalar_cost. */
- 1, /* scalar_to_vec_cost. */
- 1, /* vec_align_load_cost. */
- 2, /* vec_unalign_load_cost. */
- 1, /* vec_store_cost. */
- 3, /* cond_taken_branch_cost. */
- 1, /* cond_not_taken_branch_cost. */
-};
-
-/* Core should produce code tuned for core variants. */
-static const
-struct processor_costs core_cost = {
- COSTS_N_INSNS (1), /* cost of an add instruction */
- /* On all chips taken into consideration lea is 2 cycles and more. With
- this cost however our current implementation of synth_mult results in
- use of unnecessary temporary registers causing regression on several
- SPECfp benchmarks. */
- COSTS_N_INSNS (1) + 1, /* cost of a lea instruction */
- COSTS_N_INSNS (1), /* variable shift costs */
- COSTS_N_INSNS (1), /* constant shift costs */
- {COSTS_N_INSNS (3), /* cost of starting multiply for QI */
- COSTS_N_INSNS (4), /* HI */
- COSTS_N_INSNS (3), /* SI */
- COSTS_N_INSNS (4), /* DI */
- COSTS_N_INSNS (2)}, /* other */
- 0, /* cost of multiply per each bit set */
- {COSTS_N_INSNS (18), /* cost of a divide/mod for QI */
- COSTS_N_INSNS (26), /* HI */
- COSTS_N_INSNS (42), /* SI */
- COSTS_N_INSNS (74), /* DI */
- COSTS_N_INSNS (74)}, /* other */
- COSTS_N_INSNS (1), /* cost of movsx */
- COSTS_N_INSNS (1), /* cost of movzx */
- 8, /* "large" insn */
- 17, /* MOVE_RATIO */
- 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). */
- {4, 4, 4}, /* cost of storing integer registers */
- 4, /* cost of reg,reg fld/fst */
- {12, 12, 12}, /* cost of loading fp registers
- in SFmode, DFmode and XFmode */
- {6, 6, 8}, /* cost of storing fp registers
- in SFmode, DFmode and XFmode */
- 2, /* cost of moving MMX register */
- {8, 8}, /* cost of loading MMX registers
- in SImode and DImode */
- {8, 8}, /* cost of storing MMX registers
- in SImode and DImode */
- 2, /* cost of moving SSE register */
- {8, 8, 8}, /* cost of loading SSE registers
- in SImode, DImode and TImode */
- {8, 8, 8}, /* cost of storing SSE registers
- in SImode, DImode and TImode */
- 5, /* MMX or SSE register to integer */
- 32, /* size of l1 cache. */
- 512, /* size of l2 cache. */
- 64, /* size of prefetch block */
- 6, /* number of parallel prefetches */
- /* Benchmarks shows large regressions on K8 sixtrack benchmark when this
- value is increased to perhaps more appropriate value of 5. */
- 3, /* Branch cost */
- COSTS_N_INSNS (8), /* cost of FADD and FSUB insns. */
- COSTS_N_INSNS (8), /* cost of FMUL instruction. */
- COSTS_N_INSNS (20), /* cost of FDIV instruction. */
- COSTS_N_INSNS (8), /* cost of FABS instruction. */
- COSTS_N_INSNS (8), /* cost of FCHS instruction. */
- COSTS_N_INSNS (40), /* cost of FSQRT instruction. */
-
- /* stringop_algs for memcpy. */
- {{{libcall, {{16, loop}, {24, unrolled_loop}, {1024, rep_prefix_4_byte}, {-1, libcall}}}, /* Known alignment. */
- {libcall, {{16, loop}, {24, unrolled_loop}, {1024, rep_prefix_8_byte}, {-1, libcall}}}},
- {{libcall, {{16, loop}, {24, unrolled_loop}, {1024, rep_prefix_4_byte}, {-1, libcall}}}, /* Unknown alignment. */
- {libcall, {{16, loop}, {24, unrolled_loop}, {1024, rep_prefix_8_byte}, {-1, libcall}}}}},
-
- /* stringop_algs for memset. */
- {{{libcall, {{256, rep_prefix_4_byte}}}, /* Known alignment. */
- {libcall, {{256, rep_prefix_8_byte}}}},
- {{libcall, {{256, rep_prefix_4_byte}}}, /* Unknown alignment. */
- {libcall, {{256, rep_prefix_8_byte}}}}},
+ {{libcall, {{11, loop}, {-1, rep_prefix_4_byte}}},
+ {libcall, {{32, loop}, {64, rep_prefix_4_byte},
+ {8192, rep_prefix_8_byte}, {-1, libcall}}}},
+ {{libcall, {{8, loop}, {15, unrolled_loop},
+ {2048, rep_prefix_4_byte}, {-1, libcall}}},
+ {libcall, {{24, loop}, {32, unrolled_loop},
+ {8192, rep_prefix_8_byte}, {-1, libcall}}}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -1894,7 +1724,7 @@ struct processor_costs core_cost = {
1, /* cond_not_taken_branch_cost. */
};
-/* Generic64 should produce code tuned for Nocona, Core, K8, Amdfam10 and buldozer. */
+/* Generic64 should produce code tuned for Nocona and K8. */
static const
struct processor_costs generic64_cost = {
COSTS_N_INSNS (1), /* cost of an add instruction */
@@ -1954,16 +1784,10 @@ struct processor_costs generic64_cost = {
COSTS_N_INSNS (8), /* cost of FABS instruction. */
COSTS_N_INSNS (8), /* cost of FCHS instruction. */
COSTS_N_INSNS (40), /* cost of FSQRT instruction. */
-
- {{DUMMY_STRINGOP_ALGS,
- {libcall, {{16, rep_prefix_4_byte}, {128, rep_prefix_8_byte}, {4096, rep_prefix_1_byte}, {-1, libcall}}}},
- {DUMMY_STRINGOP_ALGS,
- {libcall, {{128, rep_prefix_4_byte}, {4096, rep_prefix_1_byte}, {-1, libcall}}}}},
-
- {{DUMMY_STRINGOP_ALGS,
- {libcall, {{16, rep_prefix_4_byte}, {512, unrolled_loop}, {4096, rep_prefix_1_byte}, {-1, libcall}}}},
- {DUMMY_STRINGOP_ALGS,
- {libcall, {{16, rep_prefix_4_byte}, {512, unrolled_loop}, {4096, rep_prefix_1_byte}, {-1, libcall}}}}},
+ {DUMMY_STRINGOP_ALGS,
+ {libcall, {{32, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
+ {DUMMY_STRINGOP_ALGS,
+ {libcall, {{32, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -1977,8 +1801,8 @@ struct processor_costs generic64_cost = {
1, /* cond_not_taken_branch_cost. */
};
-/* Generic32 should produce code tuned for PPro, Pentium4, Nocona, Core
- Athlon, K8, amdfam10, buldozer. */
+/* Generic32 should produce code tuned for PPro, Pentium4, Nocona,
+ Athlon and K8. */
static const
struct processor_costs generic32_cost = {
COSTS_N_INSNS (1), /* cost of an add instruction */
@@ -2032,16 +1856,10 @@ struct processor_costs generic32_cost = {
COSTS_N_INSNS (8), /* cost of FABS instruction. */
COSTS_N_INSNS (8), /* cost of FCHS instruction. */
COSTS_N_INSNS (40), /* cost of FSQRT instruction. */
- /* stringop_algs for memcpy. */
- {{{libcall, {{32, loop}, {8192, rep_prefix_4_byte}, {-1, libcall}}},
+ {{libcall, {{32, loop}, {8192, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
- {{libcall, {{32, loop}, {8192, rep_prefix_4_byte}, {-1, libcall}}},
- DUMMY_STRINGOP_ALGS}},
- /* stringop_algs for memset. */
- {{{libcall, {{32, loop}, {8192, rep_prefix_4_byte}, {-1, libcall}}},
+ {{libcall, {{32, loop}, {8192, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
- {{libcall, {{32, loop}, {8192, rep_prefix_4_byte}, {-1, libcall}}},
- DUMMY_STRINGOP_ALGS}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -2718,8 +2536,6 @@ static void ix86_set_current_function (tree);
static unsigned int ix86_minimum_incoming_stack_boundary (bool);
static enum calling_abi ix86_function_abi (const_tree);
-static rtx promote_duplicated_reg (enum machine_mode, rtx);
-static rtx promote_duplicated_reg_to_size (rtx, int, int, int);
#ifndef SUBTARGET32_DEFAULT_CPU
@@ -2766,13 +2582,13 @@ static const struct ptt processor_target_table[PROCESSOR_max] =
{&k8_cost, 16, 7, 16, 7, 16},
{&nocona_cost, 0, 0, 0, 0, 0},
/* Core 2 32-bit. */
- {&core_cost, 16, 10, 16, 10, 16},
+ {&generic32_cost, 16, 10, 16, 10, 16},
/* Core 2 64-bit. */
- {&core_cost, 16, 10, 16, 10, 16},
+ {&generic64_cost, 16, 10, 16, 10, 16},
/* Core i7 32-bit. */
- {&core_cost, 16, 10, 16, 10, 16},
+ {&generic32_cost, 16, 10, 16, 10, 16},
/* Core i7 64-bit. */
- {&core_cost, 16, 10, 16, 10, 16},
+ {&generic64_cost, 16, 10, 16, 10, 16},
{&generic32_cost, 16, 7, 16, 7, 16},
{&generic64_cost, 16, 10, 16, 10, 16},
{&amdfam10_cost, 32, 24, 32, 7, 32},
@@ -16457,7 +16273,6 @@ distance_non_agu_define_in_bb (unsigned int regno1, unsigned int regno2,
basic_block bb = start ? BLOCK_FOR_INSN (start) : NULL;
rtx prev = start;
rtx next = NULL;
- enum attr_type insn_type;
*found = false;
@@ -16470,8 +16285,8 @@ distance_non_agu_define_in_bb (unsigned int regno1, unsigned int regno2,
distance = increase_distance (prev, next, distance);
if (insn_defines_reg (regno1, regno2, prev))
{
- insn_type = get_attr_type (prev);
- if (insn_type != TYPE_LEA)
+ if (recog_memoized (prev) < 0
+ || get_attr_type (prev) != TYPE_LEA)
{
*found = true;
return distance;
@@ -19619,8 +19434,12 @@ ix86_expand_int_vcond (rtx operands[])
cop0 = operands[4];
cop1 = operands[5];
- /* XOP supports all of the comparisons on all vector int types. */
- if (!TARGET_XOP)
+ /* XOP supports all of the comparisons on all 128-bit vector int types. */
+ if (TARGET_XOP
+ && (mode == V16QImode || mode == V8HImode
+ || mode == V4SImode || mode == V2DImode))
+ ;
+ else
{
/* Canonicalize the comparison to EQ, GT, GTU. */
switch (code)
@@ -21107,37 +20926,22 @@ counter_mode (rtx count_exp)
return SImode;
}
-/* Helper function for expand_set_or_movmem_via_loop.
-
- When SRCPTR is non-NULL, output simple loop to move memory
+/* When SRCPTR is non-NULL, output simple loop to move memory
pointer to SRCPTR to DESTPTR via chunks of MODE unrolled UNROLL times,
overall size is COUNT specified in bytes. When SRCPTR is NULL, output the
equivalent loop to set memory by VALUE (supposed to be in MODE).
The size is rounded down to whole number of chunk size moved at once.
- SRCMEM and DESTMEM provide MEMrtx to feed proper aliasing info.
-
- If ITER isn't NULL, than it'll be used in the generated loop without
- initialization (that allows to generate several consequent loops using the
- same iterator).
- If CHANGE_PTRS is specified, DESTPTR and SRCPTR would be increased by
- iterator value at the end of the function (as if they iterate in the loop).
- Otherwise, their vaules'll stay unchanged.
+ SRCMEM and DESTMEM provide MEMrtx to feed proper aliasing info. */
- If EXPECTED_SIZE isn't -1, than it's used to compute branch-probabilities on
- the loop backedge. When expected size is unknown (it's -1), the probability
- is set to 80%.
- Return value is rtx of iterator, used in the loop - it could be reused in
- consequent calls of this function. */
-static rtx
-expand_set_or_movmem_via_loop_with_iter (rtx destmem, rtx srcmem,
- rtx destptr, rtx srcptr, rtx value,
- rtx count, rtx iter,
- enum machine_mode mode, int unroll,
- int expected_size, bool change_ptrs)
+static void
+expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem,
+ rtx destptr, rtx srcptr, rtx value,
+ rtx count, enum machine_mode mode, int unroll,
+ int expected_size)
{
- rtx out_label, top_label, tmp;
+ rtx out_label, top_label, iter, tmp;
enum machine_mode iter_mode = counter_mode (count);
rtx piece_size = GEN_INT (GET_MODE_SIZE (mode) * unroll);
rtx piece_size_mask = GEN_INT (~((GET_MODE_SIZE (mode) * unroll) - 1));
@@ -21145,12 +20949,10 @@ expand_set_or_movmem_via_loop_with_iter (rtx destmem, rtx srcmem,
rtx x_addr;
rtx y_addr;
int i;
- bool reuse_iter = (iter != NULL_RTX);
top_label = gen_label_rtx ();
out_label = gen_label_rtx ();
- if (!reuse_iter)
- iter = gen_reg_rtx (iter_mode);
+ iter = gen_reg_rtx (iter_mode);
size = expand_simple_binop (iter_mode, AND, count, piece_size_mask,
NULL, 1, OPTAB_DIRECT);
@@ -21161,21 +20963,18 @@ expand_set_or_movmem_via_loop_with_iter (rtx destmem, rtx srcmem,
true, out_label);
predict_jump (REG_BR_PROB_BASE * 10 / 100);
}
- if (!reuse_iter)
- emit_move_insn (iter, const0_rtx);
+ emit_move_insn (iter, const0_rtx);
emit_label (top_label);
tmp = convert_modes (Pmode, iter_mode, iter, true);
x_addr = gen_rtx_PLUS (Pmode, destptr, tmp);
- destmem =
- adjust_automodify_address_nv (copy_rtx (destmem), mode, x_addr, 0);
+ destmem = change_address (destmem, mode, x_addr);
if (srcmem)
{
y_addr = gen_rtx_PLUS (Pmode, srcptr, copy_rtx (tmp));
- srcmem =
- adjust_automodify_address_nv (copy_rtx (srcmem), mode, y_addr, 0);
+ srcmem = change_address (srcmem, mode, y_addr);
/* When unrolling for chips that reorder memory reads and writes,
we can save registers by using single temporary.
@@ -21247,43 +21046,19 @@ expand_set_or_movmem_via_loop_with_iter (rtx destmem, rtx srcmem,
}
else
predict_jump (REG_BR_PROB_BASE * 80 / 100);
- if (change_ptrs)
+ iter = ix86_zero_extend_to_Pmode (iter);
+ tmp = expand_simple_binop (Pmode, PLUS, destptr, iter, destptr,
+ true, OPTAB_LIB_WIDEN);
+ if (tmp != destptr)
+ emit_move_insn (destptr, tmp);
+ if (srcptr)
{
- iter = ix86_zero_extend_to_Pmode (iter);
- tmp = expand_simple_binop (Pmode, PLUS, destptr, iter, destptr,
+ tmp = expand_simple_binop (Pmode, PLUS, srcptr, iter, srcptr,
true, OPTAB_LIB_WIDEN);
- if (tmp != destptr)
- emit_move_insn (destptr, tmp);
- if (srcptr)
- {
- tmp = expand_simple_binop (Pmode, PLUS, srcptr, iter, srcptr,
- true, OPTAB_LIB_WIDEN);
- if (tmp != srcptr)
- emit_move_insn (srcptr, tmp);
- }
+ if (tmp != srcptr)
+ emit_move_insn (srcptr, tmp);
}
emit_label (out_label);
- return iter;
-}
-
-/* When SRCPTR is non-NULL, output simple loop to move memory
- pointer to SRCPTR to DESTPTR via chunks of MODE unrolled UNROLL times,
- overall size is COUNT specified in bytes. When SRCPTR is NULL, output the
- equivalent loop to set memory by VALUE (supposed to be in MODE).
-
- The size is rounded down to whole number of chunk size moved at once.
- SRCMEM and DESTMEM provide MEMrtx to feed proper aliasing info. */
-
-static void
-expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem,
- rtx destptr, rtx srcptr, rtx value,
- rtx count, enum machine_mode mode, int unroll,
- int expected_size)
-{
- expand_set_or_movmem_via_loop_with_iter (destmem, srcmem,
- destptr, srcptr, value,
- count, NULL_RTX, mode, unroll,
- expected_size, true);
}
/* Output "rep; mov" instruction.
@@ -21387,18 +21162,7 @@ emit_strmov (rtx destmem, rtx srcmem,
emit_insn (gen_strmov (destptr, dest, srcptr, src));
}
-/* Emit strset instuction. If RHS is constant, and vector mode will be used,
- then move this constant to a vector register before emitting strset. */
-static void
-emit_strset (rtx destmem, rtx value,
- rtx destptr, enum machine_mode mode, int offset)
-{
- rtx dest = adjust_automodify_address_nv (destmem, mode, destptr, offset);
- emit_insn (gen_strset (destptr, dest, value));
-}
-
-/* Output code to copy (COUNT % MAX_SIZE) bytes from SRCPTR to DESTPTR.
- SRCMEM and DESTMEM provide MEMrtx to feed proper aliasing info. */
+/* Output code to copy at most count & (max_size - 1) bytes from SRC to DEST. */
static void
expand_movmem_epilogue (rtx destmem, rtx srcmem,
rtx destptr, rtx srcptr, rtx count, int max_size)
@@ -21409,55 +21173,43 @@ expand_movmem_epilogue (rtx destmem, rtx srcmem,
HOST_WIDE_INT countval = INTVAL (count);
int offset = 0;
- int remainder_size = countval % max_size;
- enum machine_mode move_mode = Pmode;
-
- /* Firstly, try to move data with the widest possible mode.
- Remaining part we'll move using Pmode and narrower modes. */
- if (TARGET_SSE)
- {
- if (max_size >= GET_MODE_SIZE (V4SImode))
- move_mode = V4SImode;
- else if (max_size >= GET_MODE_SIZE (DImode))
- move_mode = DImode;
- }
-
- while (remainder_size >= GET_MODE_SIZE (move_mode))
+ if ((countval & 0x10) && max_size > 16)
{
- emit_strmov (destmem, srcmem, destptr, srcptr, move_mode, offset);
- offset += GET_MODE_SIZE (move_mode);
- remainder_size -= GET_MODE_SIZE (move_mode);
+ if (TARGET_64BIT)
+ {
+ emit_strmov (destmem, srcmem, destptr, srcptr, DImode, offset);
+ emit_strmov (destmem, srcmem, destptr, srcptr, DImode, offset + 8);
+ }
+ else
+ gcc_unreachable ();
+ offset += 16;
}
-
- /* Move the remaining part of epilogue - its size might be
- a size of the widest mode. */
- move_mode = Pmode;
- while (remainder_size >= GET_MODE_SIZE (move_mode))
+ if ((countval & 0x08) && max_size > 8)
{
- emit_strmov (destmem, srcmem, destptr, srcptr, move_mode, offset);
- offset += GET_MODE_SIZE (move_mode);
- remainder_size -= GET_MODE_SIZE (move_mode);
+ if (TARGET_64BIT)
+ emit_strmov (destmem, srcmem, destptr, srcptr, DImode, offset);
+ else
+ {
+ emit_strmov (destmem, srcmem, destptr, srcptr, SImode, offset);
+ emit_strmov (destmem, srcmem, destptr, srcptr, SImode, offset + 4);
+ }
+ offset += 8;
}
-
- if (remainder_size >= 4)
+ if ((countval & 0x04) && max_size > 4)
{
- emit_strmov (destmem, srcmem, destptr, srcptr, SImode, offset);
+ emit_strmov (destmem, srcmem, destptr, srcptr, SImode, offset);
offset += 4;
- remainder_size -= 4;
}
- if (remainder_size >= 2)
+ if ((countval & 0x02) && max_size > 2)
{
- emit_strmov (destmem, srcmem, destptr, srcptr, HImode, offset);
+ emit_strmov (destmem, srcmem, destptr, srcptr, HImode, offset);
offset += 2;
- remainder_size -= 2;
}
- if (remainder_size >= 1)
+ if ((countval & 0x01) && max_size > 1)
{
- emit_strmov (destmem, srcmem, destptr, srcptr, QImode, offset);
+ emit_strmov (destmem, srcmem, destptr, srcptr, QImode, offset);
offset += 1;
- remainder_size -= 1;
}
- gcc_assert (remainder_size == 0);
return;
}
if (max_size > 8)
@@ -21563,121 +21315,87 @@ expand_setmem_epilogue_via_loop (rtx destmem, rtx destptr, rtx value,
1, max_size / 2);
}
-/* Output code to set with VALUE at most (COUNT % MAX_SIZE) bytes starting from
- DESTPTR.
- DESTMEM provides MEMrtx to feed proper aliasing info.
- PROMOTED_TO_GPR_VALUE is rtx representing a GPR containing broadcasted VALUE.
- PROMOTED_TO_VECTOR_VALUE is rtx representing a vector register containing
- broadcasted VALUE.
- PROMOTED_TO_GPR_VALUE and PROMOTED_TO_VECTOR_VALUE could be NULL if the
- promotion hasn't been generated before. */
+/* Output code to set at most count & (max_size - 1) bytes starting by DEST. */
static void
-expand_setmem_epilogue (rtx destmem, rtx destptr, rtx promoted_to_vector_value,
- rtx promoted_to_gpr_value, rtx value, rtx count,
- int max_size)
+expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx count, int max_size)
{
+ rtx dest;
+
if (CONST_INT_P (count))
{
HOST_WIDE_INT countval = INTVAL (count);
int offset = 0;
- int remainder_size = countval % max_size;
- enum machine_mode move_mode = Pmode;
-
- /* Firstly, try to move data with the widest possible mode.
- Remaining part we'll move using Pmode and narrower modes. */
-
- if (promoted_to_vector_value)
- while (remainder_size >= 16)
- {
- if (GET_MODE (destmem) != move_mode)
- destmem = adjust_automodify_address_nv (destmem, move_mode,
- destptr, offset);
- emit_strset (destmem, promoted_to_vector_value, destptr,
- move_mode, offset);
-
- offset += 16;
- remainder_size -= 16;
- }
-
- /* Move the remaining part of epilogue - its size might be
- a size of the widest mode. */
- while (remainder_size >= GET_MODE_SIZE (Pmode))
+ if ((countval & 0x10) && max_size > 16)
{
- if (!promoted_to_gpr_value)
- promoted_to_gpr_value = promote_duplicated_reg (Pmode, value);
- emit_strset (destmem, promoted_to_gpr_value, destptr, Pmode, offset);
- offset += GET_MODE_SIZE (Pmode);
- remainder_size -= GET_MODE_SIZE (Pmode);
+ if (TARGET_64BIT)
+ {
+ dest = adjust_automodify_address_nv (destmem, DImode, destptr, offset);
+ emit_insn (gen_strset (destptr, dest, value));
+ dest = adjust_automodify_address_nv (destmem, DImode, destptr, offset + 8);
+ emit_insn (gen_strset (destptr, dest, value));
+ }
+ else
+ gcc_unreachable ();
+ offset += 16;
}
-
- if (!promoted_to_gpr_value && remainder_size > 1)
- promoted_to_gpr_value = promote_duplicated_reg (remainder_size >= 4
- ? SImode : HImode, value);
- if (remainder_size >= 4)
+ if ((countval & 0x08) && max_size > 8)
{
- emit_strset (destmem, gen_lowpart (SImode, promoted_to_gpr_value), destptr,
- SImode, offset);
+ if (TARGET_64BIT)
+ {
+ dest = adjust_automodify_address_nv (destmem, DImode, destptr, offset);
+ emit_insn (gen_strset (destptr, dest, value));
+ }
+ else
+ {
+ dest = adjust_automodify_address_nv (destmem, SImode, destptr, offset);
+ emit_insn (gen_strset (destptr, dest, value));
+ dest = adjust_automodify_address_nv (destmem, SImode, destptr, offset + 4);
+ emit_insn (gen_strset (destptr, dest, value));
+ }
+ offset += 8;
+ }
+ if ((countval & 0x04) && max_size > 4)
+ {
+ dest = adjust_automodify_address_nv (destmem, SImode, destptr, offset);
+ emit_insn (gen_strset (destptr, dest, gen_lowpart (SImode, value)));
offset += 4;
- remainder_size -= 4;
}
- if (remainder_size >= 2)
+ if ((countval & 0x02) && max_size > 2)
{
- emit_strset (destmem, gen_lowpart (HImode, promoted_to_gpr_value), destptr,
- HImode, offset);
- offset +=2;
- remainder_size -= 2;
+ dest = adjust_automodify_address_nv (destmem, HImode, destptr, offset);
+ emit_insn (gen_strset (destptr, dest, gen_lowpart (HImode, value)));
+ offset += 2;
}
- if (remainder_size >= 1)
+ if ((countval & 0x01) && max_size > 1)
{
- emit_strset (destmem,
- promoted_to_gpr_value ? gen_lowpart (QImode, promoted_to_gpr_value) : value,
- destptr,
- QImode, offset);
+ dest = adjust_automodify_address_nv (destmem, QImode, destptr, offset);
+ emit_insn (gen_strset (destptr, dest, gen_lowpart (QImode, value)));
offset += 1;
- remainder_size -= 1;
}
- gcc_assert (remainder_size == 0);
return;
}
-
- /* count isn't const. */
if (max_size > 32)
{
- expand_setmem_epilogue_via_loop (destmem, destptr, value, count,
- max_size);
+ expand_setmem_epilogue_via_loop (destmem, destptr, value, count, max_size);
return;
}
-
- if (!promoted_to_gpr_value)
- promoted_to_gpr_value = promote_duplicated_reg_to_size (value,
- GET_MODE_SIZE (Pmode),
- GET_MODE_SIZE (Pmode),
- GET_MODE_SIZE (Pmode));
-
if (max_size > 16)
{
rtx label = ix86_expand_aligntest (count, 16, true);
- if (TARGET_SSE && promoted_to_vector_value)
- {
- destmem = change_address (destmem,
- GET_MODE (promoted_to_vector_value),
- destptr);
- emit_insn (gen_strset (destptr, destmem, promoted_to_vector_value));
- }
- else if (TARGET_64BIT)
+ if (TARGET_64BIT)
{
- destmem = change_address (destmem, DImode, destptr);
- emit_insn (gen_strset (destptr, destmem, promoted_to_gpr_value));
- emit_insn (gen_strset (destptr, destmem, promoted_to_gpr_value));
+ dest = change_address (destmem, DImode, destptr);
+ emit_insn (gen_strset (destptr, dest, value));
+ emit_insn (gen_strset (destptr, dest, value));
}
else
{
- destmem = change_address (destmem, SImode, destptr);
- emit_insn (gen_strset (destptr, destmem, promoted_to_gpr_value));
- emit_insn (gen_strset (destptr, destmem, promoted_to_gpr_value));
- emit_insn (gen_strset (destptr, destmem, promoted_to_gpr_value));
- emit_insn (gen_strset (destptr, destmem, promoted_to_gpr_value));
+ dest = change_address (destmem, SImode, destptr);
+ emit_insn (gen_strset (destptr, dest, value));
+ emit_insn (gen_strset (destptr, dest, value));
+ emit_insn (gen_strset (destptr, dest, value));
+ emit_insn (gen_strset (destptr, dest, value));
}
emit_label (label);
LABEL_NUSES (label) = 1;
@@ -21687,22 +21405,14 @@ expand_setmem_epilogue (rtx destmem, rtx destptr, rtx promoted_to_vector_value,
rtx label = ix86_expand_aligntest (count, 8, true);
if (TARGET_64BIT)
{
- destmem = change_address (destmem, DImode, destptr);
- emit_insn (gen_strset (destptr, destmem, promoted_to_gpr_value));
- }
- /* FIXME: When this hunk it output, IRA classifies promoted_to_vector_value
- as NO_REGS. */
- else if (TARGET_SSE && promoted_to_vector_value && 0)
- {
- destmem = change_address (destmem, V2SImode, destptr);
- emit_insn (gen_strset (destptr, destmem,
- gen_lowpart (V2SImode, promoted_to_vector_value)));
+ dest = change_address (destmem, DImode, destptr);
+ emit_insn (gen_strset (destptr, dest, value));
}
else
{
- destmem = change_address (destmem, SImode, destptr);
- emit_insn (gen_strset (destptr, destmem, promoted_to_gpr_value));
- emit_insn (gen_strset (destptr, destmem, promoted_to_gpr_value));
+ dest = change_address (destmem, SImode, destptr);
+ emit_insn (gen_strset (destptr, dest, value));
+ emit_insn (gen_strset (destptr, dest, value));
}
emit_label (label);
LABEL_NUSES (label) = 1;
@@ -21710,27 +21420,24 @@ expand_setmem_epilogue (rtx destmem, rtx destptr, rtx promoted_to_vector_value,
if (max_size > 4)
{
rtx label = ix86_expand_aligntest (count, 4, true);
- destmem = change_address (destmem, SImode, destptr);
- emit_insn (gen_strset (destptr, destmem,
- gen_lowpart (SImode, promoted_to_gpr_value)));
+ dest = change_address (destmem, SImode, destptr);
+ emit_insn (gen_strset (destptr, dest, gen_lowpart (SImode, value)));
emit_label (label);
LABEL_NUSES (label) = 1;
}
if (max_size > 2)
{
rtx label = ix86_expand_aligntest (count, 2, true);
- destmem = change_address (destmem, HImode, destptr);
- emit_insn (gen_strset (destptr, destmem,
- gen_lowpart (HImode, promoted_to_gpr_value)));
+ dest = change_address (destmem, HImode, destptr);
+ emit_insn (gen_strset (destptr, dest, gen_lowpart (HImode, value)));
emit_label (label);
LABEL_NUSES (label) = 1;
}
if (max_size > 1)
{
rtx label = ix86_expand_aligntest (count, 1, true);
- destmem = change_address (destmem, QImode, destptr);
- emit_insn (gen_strset (destptr, destmem,
- gen_lowpart (QImode, promoted_to_gpr_value)));
+ dest = change_address (destmem, QImode, destptr);
+ emit_insn (gen_strset (destptr, dest, gen_lowpart (QImode, value)));
emit_label (label);
LABEL_NUSES (label) = 1;
}
@@ -21746,8 +21453,8 @@ expand_movmem_prologue (rtx destmem, rtx srcmem,
if (align <= 1 && desired_alignment > 1)
{
rtx label = ix86_expand_aligntest (destptr, 1, false);
- srcmem = adjust_automodify_address_nv (srcmem, QImode, srcptr, 0);
- destmem = adjust_automodify_address_nv (destmem, QImode, destptr, 0);
+ srcmem = change_address (srcmem, QImode, srcptr);
+ destmem = change_address (destmem, QImode, destptr);
emit_insn (gen_strmov (destptr, destmem, srcptr, srcmem));
ix86_adjust_counter (count, 1);
emit_label (label);
@@ -21756,8 +21463,8 @@ expand_movmem_prologue (rtx destmem, rtx srcmem,
if (align <= 2 && desired_alignment > 2)
{
rtx label = ix86_expand_aligntest (destptr, 2, false);
- srcmem = adjust_automodify_address_nv (srcmem, HImode, srcptr, 0);
- destmem = adjust_automodify_address_nv (destmem, HImode, destptr, 0);
+ srcmem = change_address (srcmem, HImode, srcptr);
+ destmem = change_address (destmem, HImode, destptr);
emit_insn (gen_strmov (destptr, destmem, srcptr, srcmem));
ix86_adjust_counter (count, 2);
emit_label (label);
@@ -21766,34 +21473,14 @@ expand_movmem_prologue (rtx destmem, rtx srcmem,
if (align <= 4 && desired_alignment > 4)
{
rtx label = ix86_expand_aligntest (destptr, 4, false);
- srcmem = adjust_automodify_address_nv (srcmem, SImode, srcptr, 0);
- destmem = adjust_automodify_address_nv (destmem, SImode, destptr, 0);
+ srcmem = change_address (srcmem, SImode, srcptr);
+ destmem = change_address (destmem, SImode, destptr);
emit_insn (gen_strmov (destptr, destmem, srcptr, srcmem));
ix86_adjust_counter (count, 4);
emit_label (label);
LABEL_NUSES (label) = 1;
}
- if (align <= 8 && desired_alignment > 8)
- {
- rtx label = ix86_expand_aligntest (destptr, 8, false);
- if (TARGET_64BIT || TARGET_SSE)
- {
- srcmem = adjust_automodify_address_nv (srcmem, DImode, srcptr, 0);
- destmem = adjust_automodify_address_nv (destmem, DImode, destptr, 0);
- emit_insn (gen_strmov (destptr, destmem, srcptr, srcmem));
- }
- else
- {
- srcmem = adjust_automodify_address_nv (srcmem, SImode, srcptr, 0);
- destmem = adjust_automodify_address_nv (destmem, SImode, destptr, 0);
- emit_insn (gen_strmov (destptr, destmem, srcptr, srcmem));
- emit_insn (gen_strmov (destptr, destmem, srcptr, srcmem));
- }
- ix86_adjust_counter (count, 8);
- emit_label (label);
- LABEL_NUSES (label) = 1;
- }
- gcc_assert (desired_alignment <= 16);
+ gcc_assert (desired_alignment <= 8);
}
/* Copy enough from DST to SRC to align DST known to DESIRED_ALIGN.
@@ -21848,37 +21535,6 @@ expand_constant_movmem_prologue (rtx dst, rtx *srcp, rtx destreg, rtx srcreg,
off = 4;
emit_insn (gen_strmov (destreg, dst, srcreg, src));
}
- if (align_bytes & 8)
- {
- if (TARGET_64BIT || TARGET_SSE)
- {
- dst = adjust_automodify_address_nv (dst, DImode, destreg, off);
- src = adjust_automodify_address_nv (src, DImode, srcreg, off);
- emit_insn (gen_strmov (destreg, dst, srcreg, src));
- }
- else
- {
- dst = adjust_automodify_address_nv (dst, SImode, destreg, off);
- src = adjust_automodify_address_nv (src, SImode, srcreg, off);
- emit_insn (gen_strmov (destreg, dst, srcreg, src));
- emit_insn (gen_strmov (destreg, dst, srcreg, src));
- }
- if (MEM_ALIGN (dst) < 8 * BITS_PER_UNIT)
- set_mem_align (dst, 8 * BITS_PER_UNIT);
- if (src_align_bytes >= 0)
- {
- unsigned int src_align = 0;
- if ((src_align_bytes & 7) == (align_bytes & 7))
- src_align = 8;
- else if ((src_align_bytes & 3) == (align_bytes & 3))
- src_align = 4;
- else if ((src_align_bytes & 1) == (align_bytes & 1))
- src_align = 2;
- if (MEM_ALIGN (src) < src_align * BITS_PER_UNIT)
- set_mem_align (src, src_align * BITS_PER_UNIT);
- }
- off = 8;
- }
dst = adjust_automodify_address_nv (dst, BLKmode, destreg, off);
src = adjust_automodify_address_nv (src, BLKmode, srcreg, off);
if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT)
@@ -21886,9 +21542,7 @@ expand_constant_movmem_prologue (rtx dst, rtx *srcp, rtx destreg, rtx srcreg,
if (src_align_bytes >= 0)
{
unsigned int src_align = 0;
- if ((src_align_bytes & 15) == (align_bytes & 15))
- src_align = 16;
- else if ((src_align_bytes & 7) == (align_bytes & 7))
+ if ((src_align_bytes & 7) == (align_bytes & 7))
src_align = 8;
else if ((src_align_bytes & 3) == (align_bytes & 3))
src_align = 4;
@@ -21916,7 +21570,7 @@ expand_setmem_prologue (rtx destmem, rtx destptr, rtx value, rtx count,
if (align <= 1 && desired_alignment > 1)
{
rtx label = ix86_expand_aligntest (destptr, 1, false);
- destmem = adjust_automodify_address_nv (destmem, QImode, destptr, 0);
+ destmem = change_address (destmem, QImode, destptr);
emit_insn (gen_strset (destptr, destmem, gen_lowpart (QImode, value)));
ix86_adjust_counter (count, 1);
emit_label (label);
@@ -21925,7 +21579,7 @@ expand_setmem_prologue (rtx destmem, rtx destptr, rtx value, rtx count,
if (align <= 2 && desired_alignment > 2)
{
rtx label = ix86_expand_aligntest (destptr, 2, false);
- destmem = adjust_automodify_address_nv (destmem, HImode, destptr, 0);
+ destmem = change_address (destmem, HImode, destptr);
emit_insn (gen_strset (destptr, destmem, gen_lowpart (HImode, value)));
ix86_adjust_counter (count, 2);
emit_label (label);
@@ -21934,23 +21588,13 @@ expand_setmem_prologue (rtx destmem, rtx destptr, rtx value, rtx count,
if (align <= 4 && desired_alignment > 4)
{
rtx label = ix86_expand_aligntest (destptr, 4, false);
- destmem = adjust_automodify_address_nv (destmem, SImode, destptr, 0);
+ destmem = change_address (destmem, SImode, destptr);
emit_insn (gen_strset (destptr, destmem, gen_lowpart (SImode, value)));
ix86_adjust_counter (count, 4);
emit_label (label);
LABEL_NUSES (label) = 1;
}
- if (align <= 8 && desired_alignment > 8)
- {
- rtx label = ix86_expand_aligntest (destptr, 8, false);
- destmem = adjust_automodify_address_nv (destmem, SImode, destptr, 0);
- emit_insn (gen_strset (destptr, destmem, gen_lowpart (SImode, value)));
- emit_insn (gen_strset (destptr, destmem, gen_lowpart (SImode, value)));
- ix86_adjust_counter (count, 8);
- emit_label (label);
- LABEL_NUSES (label) = 1;
- }
- gcc_assert (desired_alignment <= 16);
+ gcc_assert (desired_alignment <= 8);
}
/* Set enough from DST to align DST known to by aligned by ALIGN to
@@ -21986,19 +21630,6 @@ expand_constant_setmem_prologue (rtx dst, rtx destreg, rtx value,
emit_insn (gen_strset (destreg, dst,
gen_lowpart (SImode, value)));
}
- if (align_bytes & 8)
- {
- dst = adjust_automodify_address_nv (dst, SImode, destreg, off);
- emit_insn (gen_strset (destreg, dst,
- gen_lowpart (SImode, value)));
- off = 4;
- dst = adjust_automodify_address_nv (dst, SImode, destreg, off);
- emit_insn (gen_strset (destreg, dst,
- gen_lowpart (SImode, value)));
- if (MEM_ALIGN (dst) < 8 * BITS_PER_UNIT)
- set_mem_align (dst, 8 * BITS_PER_UNIT);
- off = 4;
- }
dst = adjust_automodify_address_nv (dst, BLKmode, destreg, off);
if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT)
set_mem_align (dst, desired_align * BITS_PER_UNIT);
@@ -22010,7 +21641,7 @@ expand_constant_setmem_prologue (rtx dst, rtx destreg, rtx value,
/* Given COUNT and EXPECTED_SIZE, decide on codegen of string operation. */
static enum stringop_alg
decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset,
- int *dynamic_check, bool align_unknown)
+ int *dynamic_check)
{
const struct stringop_algs * algs;
bool optimize_for_speed;
@@ -22019,7 +21650,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset,
consider such algorithms if the user has appropriated those
registers for their own purposes. */
bool rep_prefix_usable = !(fixed_regs[CX_REG] || fixed_regs[DI_REG]
- || (memset
+ || (memset
? fixed_regs[AX_REG] : fixed_regs[SI_REG]));
#define ALG_USABLE_P(alg) (rep_prefix_usable \
@@ -22032,7 +21663,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset,
of time processing large blocks. */
if (optimize_function_for_size_p (cfun)
|| (optimize_insn_for_size_p ()
- && expected_size != -1 && expected_size < 256))
+ && expected_size != -1 && expected_size < 256))
optimize_for_speed = false;
else
optimize_for_speed = true;
@@ -22041,9 +21672,9 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset,
*dynamic_check = -1;
if (memset)
- algs = &cost->memset[align_unknown][TARGET_64BIT != 0];
+ algs = &cost->memset[TARGET_64BIT != 0];
else
- algs = &cost->memcpy[align_unknown][TARGET_64BIT != 0];
+ algs = &cost->memcpy[TARGET_64BIT != 0];
if (ix86_stringop_alg != no_stringop && ALG_USABLE_P (ix86_stringop_alg))
return ix86_stringop_alg;
/* rep; movq or rep; movl is the smallest variant. */
@@ -22107,33 +21738,29 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset,
enum stringop_alg alg;
int i;
bool any_alg_usable_p = true;
- bool only_libcall_fits = true;
for (i = 0; i < MAX_STRINGOP_ALGS; i++)
- {
- enum stringop_alg candidate = algs->size[i].alg;
- any_alg_usable_p = any_alg_usable_p && ALG_USABLE_P (candidate);
+ {
+ enum stringop_alg candidate = algs->size[i].alg;
+ any_alg_usable_p = any_alg_usable_p && ALG_USABLE_P (candidate);
- if (candidate != libcall && candidate
- && ALG_USABLE_P (candidate))
- {
- max = algs->size[i].max;
- only_libcall_fits = false;
- }
- }
+ if (candidate != libcall && candidate
+ && ALG_USABLE_P (candidate))
+ max = algs->size[i].max;
+ }
/* If there aren't any usable algorithms, then recursing on
- smaller sizes isn't going to find anything. Just return the
- simple byte-at-a-time copy loop. */
- if (!any_alg_usable_p || only_libcall_fits)
- {
- /* Pick something reasonable. */
- if (TARGET_INLINE_STRINGOPS_DYNAMICALLY)
- *dynamic_check = 128;
- return loop_1_byte;
- }
+ smaller sizes isn't going to find anything. Just return the
+ simple byte-at-a-time copy loop. */
+ if (!any_alg_usable_p)
+ {
+ /* Pick something reasonable. */
+ if (TARGET_INLINE_STRINGOPS_DYNAMICALLY)
+ *dynamic_check = 128;
+ return loop_1_byte;
+ }
if (max == -1)
max = 4096;
- alg = decide_alg (count, max / 2, memset, dynamic_check, align_unknown);
+ alg = decide_alg (count, max / 2, memset, dynamic_check);
gcc_assert (*dynamic_check == -1);
gcc_assert (alg != libcall);
if (TARGET_INLINE_STRINGOPS_DYNAMICALLY)
@@ -22157,14 +21784,9 @@ decide_alignment (int align,
case no_stringop:
gcc_unreachable ();
case loop:
- desired_align = GET_MODE_SIZE (Pmode);
- break;
case unrolled_loop:
desired_align = GET_MODE_SIZE (Pmode);
break;
- case sse_loop:
- desired_align = 16;
- break;
case rep_prefix_8_byte:
desired_align = 8;
break;
@@ -22252,11 +21874,6 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
enum stringop_alg alg;
int dynamic_check;
bool need_zero_guard = false;
- bool align_unknown;
- int unroll_factor;
- enum machine_mode move_mode;
- rtx loop_iter = NULL_RTX;
- int dst_offset, src_offset;
if (CONST_INT_P (align_exp))
align = INTVAL (align_exp);
@@ -22280,17 +21897,9 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
/* Step 0: Decide on preferred algorithm, desired alignment and
size of chunks to be copied by main loop. */
- dst_offset = get_mem_align_offset (dst, MOVE_MAX*BITS_PER_UNIT);
- src_offset = get_mem_align_offset (src, MOVE_MAX*BITS_PER_UNIT);
- align_unknown = (dst_offset < 0
- || src_offset < 0
- || src_offset != dst_offset);
- alg = decide_alg (count, expected_size, false, &dynamic_check, align_unknown);
+
+ alg = decide_alg (count, expected_size, false, &dynamic_check);
desired_align = decide_alignment (align, alg, expected_size);
- if (align_unknown)
- desired_align = align;
- unroll_factor = 1;
- move_mode = Pmode;
if (!TARGET_ALIGN_STRINGOPS)
align = desired_align;
@@ -22309,22 +21918,11 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
gcc_unreachable ();
case loop:
need_zero_guard = true;
- move_mode = Pmode;
- unroll_factor = 1;
- size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
+ size_needed = GET_MODE_SIZE (Pmode);
break;
case unrolled_loop:
need_zero_guard = true;
- move_mode = Pmode;
- unroll_factor = TARGET_64BIT ? 4 : 2;
- size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
- break;
- case sse_loop:
- need_zero_guard = true;
- /* Use SSE instructions, if possible. */
- move_mode = align_unknown ? DImode : V4SImode;
- unroll_factor = TARGET_64BIT ? 4 : 2;
- size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
+ size_needed = GET_MODE_SIZE (Pmode) * (TARGET_64BIT ? 4 : 2);
break;
case rep_prefix_8_byte:
size_needed = 8;
@@ -22385,12 +21983,6 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
}
else
{
- /* SSE and unrolled algs re-use iteration counter in the epilogue. */
- if (alg == sse_loop || alg == unrolled_loop)
- {
- loop_iter = gen_reg_rtx (counter_mode (count_exp));
- emit_move_insn (loop_iter, const0_rtx);
- }
label = gen_label_rtx ();
emit_cmp_and_jump_insns (count_exp,
GEN_INT (epilogue_size_needed),
@@ -22442,8 +22034,6 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
dst = change_address (dst, BLKmode, destreg);
expand_movmem_prologue (dst, src, destreg, srcreg, count_exp, align,
desired_align);
- set_mem_align (src, desired_align*BITS_PER_UNIT);
- set_mem_align (dst, desired_align*BITS_PER_UNIT);
}
else
{
@@ -22500,16 +22090,12 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
expand_set_or_movmem_via_loop (dst, src, destreg, srcreg, NULL,
count_exp, Pmode, 1, expected_size);
break;
- case sse_loop:
case unrolled_loop:
- /* In some cases we want to use the same iterator in several adjacent
- loops, so here we save loop iterator rtx and don't update addresses. */
- loop_iter = expand_set_or_movmem_via_loop_with_iter (dst, src, destreg,
- srcreg, NULL,
- count_exp, loop_iter,
- move_mode,
- unroll_factor,
- expected_size, false);
+ /* Unroll only by factor of 2 in 32bit mode, since we don't have enough
+ registers for 4 temporaries anyway. */
+ expand_set_or_movmem_via_loop (dst, src, destreg, srcreg, NULL,
+ count_exp, Pmode, TARGET_64BIT ? 4 : 2,
+ expected_size);
break;
case rep_prefix_8_byte:
expand_movmem_via_rep_mov (dst, src, destreg, srcreg, count_exp,
@@ -22560,41 +22146,9 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
LABEL_NUSES (label) = 1;
}
- /* We haven't updated addresses, so we'll do it now.
- Also, if the epilogue seems to be big, we'll generate a loop (not
- unrolled) in it. We'll do it only if alignment is unknown, because in
- this case in epilogue we have to perform memmove by bytes, which is very
- slow. */
- if (alg == sse_loop || alg == unrolled_loop)
- {
- rtx tmp;
- if (align_unknown && unroll_factor > 1)
- {
- /* Reduce epilogue's size by creating not-unrolled loop. If we won't
- do this, we can have very big epilogue - when alignment is statically
- unknown we'll have the epilogue byte by byte which may be very slow. */
- loop_iter = expand_set_or_movmem_via_loop_with_iter (dst, src, destreg,
- srcreg, NULL, count_exp,
- loop_iter, move_mode, 1,
- expected_size, false);
- src = change_address (src, BLKmode, srcreg);
- dst = change_address (dst, BLKmode, destreg);
- epilogue_size_needed = GET_MODE_SIZE (move_mode);
- }
- tmp = expand_simple_binop (Pmode, PLUS, destreg, loop_iter, destreg,
- true, OPTAB_LIB_WIDEN);
- if (tmp != destreg)
- emit_move_insn (destreg, tmp);
-
- tmp = expand_simple_binop (Pmode, PLUS, srcreg, loop_iter, srcreg,
- true, OPTAB_LIB_WIDEN);
- if (tmp != srcreg)
- emit_move_insn (srcreg, tmp);
- }
if (count_exp != const0_rtx && epilogue_size_needed > 1)
expand_movmem_epilogue (dst, src, destreg, srcreg, count_exp,
epilogue_size_needed);
-
if (jump_around_label)
emit_label (jump_around_label);
return true;
@@ -22612,37 +22166,7 @@ promote_duplicated_reg (enum machine_mode mode, rtx val)
rtx tmp;
int nops = mode == DImode ? 3 : 2;
- if (VECTOR_MODE_P (mode))
- {
- enum machine_mode inner = GET_MODE_INNER (mode);
- rtx promoted_val, vec_reg;
- if (CONST_INT_P (val))
- return ix86_build_const_vector (mode, true, val);
-
- promoted_val = promote_duplicated_reg (inner, val);
- vec_reg = gen_reg_rtx (mode);
- switch (mode)
- {
- case V2DImode:
- emit_insn (gen_vec_dupv2di (vec_reg, promoted_val));
- break;
- case V4SImode:
- emit_insn (gen_vec_dupv4si (vec_reg, promoted_val));
- break;
- default:
- gcc_unreachable ();
- break;
- }
-
- return vec_reg;
- }
gcc_assert (mode == SImode || mode == DImode);
- if (mode == DImode && !TARGET_64BIT)
- {
- rtx vec_reg = promote_duplicated_reg (V4SImode, val);
- vec_reg = convert_to_mode (V2DImode, vec_reg, 1);
- return vec_reg;
- }
if (val == const0_rtx)
return copy_to_mode_reg (mode, const0_rtx);
if (CONST_INT_P (val))
@@ -22708,27 +22232,11 @@ promote_duplicated_reg (enum machine_mode mode, rtx val)
static rtx
promote_duplicated_reg_to_size (rtx val, int size_needed, int desired_align, int align)
{
- rtx promoted_val = NULL_RTX;
+ rtx promoted_val;
- if (size_needed > 8 || (desired_align > align && desired_align > 8))
- {
- /* We want to promote to vector register, so we expect that at least SSE
- is available. */
- gcc_assert (TARGET_SSE);
-
- /* In case of promotion to vector register, we expect that val is a
- constant or already promoted to GPR value. */
- gcc_assert (GET_MODE (val) == Pmode || CONSTANT_P (val));
- if (TARGET_64BIT)
- promoted_val = promote_duplicated_reg (V2DImode, val);
- else
- promoted_val = promote_duplicated_reg (V4SImode, val);
- }
- else if (size_needed > 4 || (desired_align > align && desired_align > 4))
- {
- gcc_assert (TARGET_64BIT);
- promoted_val = promote_duplicated_reg (DImode, val);
- }
+ if (TARGET_64BIT
+ && (size_needed > 4 || (desired_align > align && desired_align > 4)))
+ promoted_val = promote_duplicated_reg (DImode, val);
else if (size_needed > 2 || (desired_align > align && desired_align > 2))
promoted_val = promote_duplicated_reg (SImode, val);
else if (size_needed > 1 || (desired_align > align && desired_align > 1))
@@ -22756,14 +22264,10 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
int size_needed = 0, epilogue_size_needed;
int desired_align = 0, align_bytes = 0;
enum stringop_alg alg;
- rtx gpr_promoted_val = NULL;
- rtx vec_promoted_val = NULL;
+ rtx promoted_val = NULL;
+ bool force_loopy_epilogue = false;
int dynamic_check;
bool need_zero_guard = false;
- bool align_unknown;
- unsigned int unroll_factor;
- enum machine_mode move_mode;
- rtx loop_iter = NULL_RTX;
if (CONST_INT_P (align_exp))
align = INTVAL (align_exp);
@@ -22783,11 +22287,8 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
/* Step 0: Decide on preferred algorithm, desired alignment and
size of chunks to be copied by main loop. */
- align_unknown = CONST_INT_P (align_exp) && INTVAL (align_exp) > 0;
- alg = decide_alg (count, expected_size, true, &dynamic_check, align_unknown);
+ alg = decide_alg (count, expected_size, true, &dynamic_check);
desired_align = decide_alignment (align, alg, expected_size);
- unroll_factor = 1;
- move_mode = Pmode;
if (!TARGET_ALIGN_STRINGOPS)
align = desired_align;
@@ -22805,28 +22306,11 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
gcc_unreachable ();
case loop:
need_zero_guard = true;
- move_mode = Pmode;
- size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
+ size_needed = GET_MODE_SIZE (Pmode);
break;
case unrolled_loop:
need_zero_guard = true;
- move_mode = Pmode;
- unroll_factor = 1;
- /* Select maximal available 1,2 or 4 unroll factor. */
- while (GET_MODE_SIZE (move_mode) * unroll_factor * 2 < count
- && unroll_factor < 4)
- unroll_factor *= 2;
- size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
- break;
- case sse_loop:
- need_zero_guard = true;
- move_mode = TARGET_64BIT ? V2DImode : V4SImode;
- unroll_factor = 1;
- /* Select maximal available 1,2 or 4 unroll factor. */
- while (GET_MODE_SIZE (move_mode) * unroll_factor * 2 < count
- && unroll_factor < 4)
- unroll_factor *= 2;
- size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
+ size_needed = GET_MODE_SIZE (Pmode) * 4;
break;
case rep_prefix_8_byte:
size_needed = 8;
@@ -22871,10 +22355,8 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
main loop and epilogue (ie one load of the big constant in the
front of all code. */
if (CONST_INT_P (val_exp))
- gpr_promoted_val = promote_duplicated_reg_to_size (val_exp,
- GET_MODE_SIZE (Pmode),
- GET_MODE_SIZE (Pmode),
- align);
+ promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
+ desired_align, align);
/* Ensure that alignment prologue won't copy past end of block. */
if (size_needed > 1 || (desired_align > 1 && desired_align > align))
{
@@ -22883,6 +22365,12 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
Make sure it is power of 2. */
epilogue_size_needed = smallest_pow2_greater_than (epilogue_size_needed);
+ /* To improve performance of small blocks, we jump around the VAL
+ promoting mode. This mean that if the promoted VAL is not constant,
+ we might not use it in the epilogue and have to use byte
+ loop variant. */
+ if (epilogue_size_needed > 2 && !promoted_val)
+ force_loopy_epilogue = true;
if (count)
{
if (count < (unsigned HOST_WIDE_INT)epilogue_size_needed)
@@ -22897,12 +22385,6 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
}
else
{
- /* SSE and unrolled_lopo algs re-use iteration counter in the epilogue. */
- if (alg == sse_loop || alg == unrolled_loop)
- {
- loop_iter = gen_reg_rtx (counter_mode (count_exp));
- emit_move_insn (loop_iter, const0_rtx);
- }
label = gen_label_rtx ();
emit_cmp_and_jump_insns (count_exp,
GEN_INT (epilogue_size_needed),
@@ -22928,11 +22410,9 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
/* Step 2: Alignment prologue. */
/* Do the expensive promotion once we branched off the small blocks. */
- if (!gpr_promoted_val)
- gpr_promoted_val = promote_duplicated_reg_to_size (val_exp,
- GET_MODE_SIZE (Pmode),
- GET_MODE_SIZE (Pmode),
- align);
+ if (!promoted_val)
+ promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
+ desired_align, align);
gcc_assert (desired_align >= 1 && align >= 1);
if (desired_align > align)
@@ -22944,20 +22424,17 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
the pain to maintain it for the first move, so throw away
the info early. */
dst = change_address (dst, BLKmode, destreg);
- expand_setmem_prologue (dst, destreg, gpr_promoted_val, count_exp, align,
+ expand_setmem_prologue (dst, destreg, promoted_val, count_exp, align,
desired_align);
- set_mem_align (dst, desired_align*BITS_PER_UNIT);
}
else
{
/* If we know how many bytes need to be stored before dst is
sufficiently aligned, maintain aliasing info accurately. */
- dst = expand_constant_setmem_prologue (dst, destreg, gpr_promoted_val,
+ dst = expand_constant_setmem_prologue (dst, destreg, promoted_val,
desired_align, align_bytes);
count_exp = plus_constant (count_exp, -align_bytes);
count -= align_bytes;
- if (count < (unsigned HOST_WIDE_INT) size_needed)
- goto epilogue;
}
if (need_zero_guard
&& (count < (unsigned HOST_WIDE_INT) size_needed
@@ -22985,7 +22462,7 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
emit_label (label);
LABEL_NUSES (label) = 1;
label = NULL;
- gpr_promoted_val = val_exp;
+ promoted_val = val_exp;
epilogue_size_needed = 1;
}
else if (label == NULL_RTX)
@@ -22999,40 +22476,27 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
case no_stringop:
gcc_unreachable ();
case loop_1_byte:
- expand_set_or_movmem_via_loop (dst, NULL, destreg, NULL, val_exp,
+ expand_set_or_movmem_via_loop (dst, NULL, destreg, NULL, promoted_val,
count_exp, QImode, 1, expected_size);
break;
case loop:
- expand_set_or_movmem_via_loop (dst, NULL, destreg, NULL, gpr_promoted_val,
+ expand_set_or_movmem_via_loop (dst, NULL, destreg, NULL, promoted_val,
count_exp, Pmode, 1, expected_size);
break;
case unrolled_loop:
- loop_iter = expand_set_or_movmem_via_loop_with_iter (dst, NULL, destreg,
- NULL, gpr_promoted_val, count_exp,
- loop_iter, move_mode, unroll_factor,
- expected_size, false);
- break;
- case sse_loop:
- vec_promoted_val =
- promote_duplicated_reg_to_size (gpr_promoted_val,
- GET_MODE_SIZE (move_mode),
- desired_align, align);
- loop_iter = expand_set_or_movmem_via_loop_with_iter (dst, NULL, destreg,
- NULL, vec_promoted_val, count_exp,
- loop_iter, move_mode, unroll_factor,
- expected_size, false);
+ expand_set_or_movmem_via_loop (dst, NULL, destreg, NULL, promoted_val,
+ count_exp, Pmode, 4, expected_size);
break;
case rep_prefix_8_byte:
- gcc_assert (TARGET_64BIT);
- expand_setmem_via_rep_stos (dst, destreg, gpr_promoted_val, count_exp,
+ expand_setmem_via_rep_stos (dst, destreg, promoted_val, count_exp,
DImode, val_exp);
break;
case rep_prefix_4_byte:
- expand_setmem_via_rep_stos (dst, destreg, gpr_promoted_val, count_exp,
+ expand_setmem_via_rep_stos (dst, destreg, promoted_val, count_exp,
SImode, val_exp);
break;
case rep_prefix_1_byte:
- expand_setmem_via_rep_stos (dst, destreg, gpr_promoted_val, count_exp,
+ expand_setmem_via_rep_stos (dst, destreg, promoted_val, count_exp,
QImode, val_exp);
break;
}
@@ -23063,43 +22527,16 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
}
emit_label (label);
LABEL_NUSES (label) = 1;
- /* We can not rely on fact that promoved value is known. */
- vec_promoted_val = 0;
- gpr_promoted_val = 0;
}
epilogue:
- if (alg == unrolled_loop || alg == sse_loop)
- {
- rtx tmp;
- if (align_unknown && unroll_factor > 1
- && epilogue_size_needed >= GET_MODE_SIZE (move_mode)
- && vec_promoted_val)
- {
- /* Reduce epilogue's size by creating not-unrolled loop. If we won't
- do this, we can have very big epilogue - when alignment is statically
- unknown we'll have the epilogue byte by byte which may be very slow. */
- loop_iter = expand_set_or_movmem_via_loop_with_iter (dst, NULL, destreg,
- NULL, vec_promoted_val, count_exp,
- loop_iter, move_mode, 1,
- expected_size, false);
- dst = change_address (dst, BLKmode, destreg);
- epilogue_size_needed = GET_MODE_SIZE (move_mode);
- }
- tmp = expand_simple_binop (Pmode, PLUS, destreg, loop_iter, destreg,
- true, OPTAB_LIB_WIDEN);
- if (tmp != destreg)
- emit_move_insn (destreg, tmp);
- }
- if (count_exp == const0_rtx)
- ;
- else if (!gpr_promoted_val && epilogue_size_needed > 1)
- expand_setmem_epilogue_via_loop (dst, destreg, val_exp, count_exp,
- epilogue_size_needed);
- else
+ if (count_exp != const0_rtx && epilogue_size_needed > 1)
{
- if (epilogue_size_needed > 1)
- expand_setmem_epilogue (dst, destreg, vec_promoted_val, gpr_promoted_val,
- val_exp, count_exp, epilogue_size_needed);
+ if (force_loopy_epilogue)
+ expand_setmem_epilogue_via_loop (dst, destreg, val_exp, count_exp,
+ epilogue_size_needed);
+ else
+ expand_setmem_epilogue (dst, destreg, promoted_val, count_exp,
+ epilogue_size_needed);
}
if (jump_around_label)
emit_label (jump_around_label);
@@ -25245,6 +24682,7 @@ enum ix86_builtins
IX86_BUILTIN_CVTTPS2DQ,
IX86_BUILTIN_MOVNTI,
+ IX86_BUILTIN_MOVNTI64,
IX86_BUILTIN_MOVNTPD,
IX86_BUILTIN_MOVNTDQ,
@@ -25457,22 +24895,32 @@ enum ix86_builtins
IX86_BUILTIN_PMULDQ128,
IX86_BUILTIN_PMULLD128,
- IX86_BUILTIN_ROUNDPD,
- IX86_BUILTIN_ROUNDPS,
IX86_BUILTIN_ROUNDSD,
IX86_BUILTIN_ROUNDSS,
+ IX86_BUILTIN_ROUNDPD,
+ IX86_BUILTIN_ROUNDPS,
+
IX86_BUILTIN_FLOORPD,
IX86_BUILTIN_CEILPD,
IX86_BUILTIN_TRUNCPD,
IX86_BUILTIN_RINTPD,
IX86_BUILTIN_ROUNDPD_AZ,
+
+ IX86_BUILTIN_FLOORPD_VEC_PACK_SFIX,
+ IX86_BUILTIN_CEILPD_VEC_PACK_SFIX,
+ IX86_BUILTIN_ROUNDPD_AZ_VEC_PACK_SFIX,
+
IX86_BUILTIN_FLOORPS,
IX86_BUILTIN_CEILPS,
IX86_BUILTIN_TRUNCPS,
IX86_BUILTIN_RINTPS,
IX86_BUILTIN_ROUNDPS_AZ,
+ IX86_BUILTIN_FLOORPS_SFIX,
+ IX86_BUILTIN_CEILPS_SFIX,
+ IX86_BUILTIN_ROUNDPS_AZ_SFIX,
+
IX86_BUILTIN_PTESTZ,
IX86_BUILTIN_PTESTC,
IX86_BUILTIN_PTESTNZC,
@@ -25646,12 +25094,21 @@ enum ix86_builtins
IX86_BUILTIN_TRUNCPD256,
IX86_BUILTIN_RINTPD256,
IX86_BUILTIN_ROUNDPD_AZ256,
+
+ IX86_BUILTIN_FLOORPD_VEC_PACK_SFIX256,
+ IX86_BUILTIN_CEILPD_VEC_PACK_SFIX256,
+ IX86_BUILTIN_ROUNDPD_AZ_VEC_PACK_SFIX256,
+
IX86_BUILTIN_FLOORPS256,
IX86_BUILTIN_CEILPS256,
IX86_BUILTIN_TRUNCPS256,
IX86_BUILTIN_RINTPS256,
IX86_BUILTIN_ROUNDPS_AZ256,
+ IX86_BUILTIN_FLOORPS_SFIX256,
+ IX86_BUILTIN_CEILPS_SFIX256,
+ IX86_BUILTIN_ROUNDPS_AZ_SFIX256,
+
IX86_BUILTIN_UNPCKHPD256,
IX86_BUILTIN_UNPCKLPD256,
IX86_BUILTIN_UNPCKHPS256,
@@ -26299,7 +25756,7 @@ static const struct builtin_description bdesc_special_args[] =
/* SSE or 3DNow!A */
{ OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_3DNOW_A, CODE_FOR_sse_sfence, "__builtin_ia32_sfence", IX86_BUILTIN_SFENCE, UNKNOWN, (int) VOID_FTYPE_VOID },
- { OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_3DNOW_A, CODE_FOR_sse_movntdi, "__builtin_ia32_movntq", IX86_BUILTIN_MOVNTQ, UNKNOWN, (int) VOID_FTYPE_PULONGLONG_ULONGLONG },
+ { OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_3DNOW_A, CODE_FOR_sse_movntq, "__builtin_ia32_movntq", IX86_BUILTIN_MOVNTQ, UNKNOWN, (int) VOID_FTYPE_PULONGLONG_ULONGLONG },
/* SSE2 */
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_lfence, "__builtin_ia32_lfence", IX86_BUILTIN_LFENCE, UNKNOWN, (int) VOID_FTYPE_VOID },
@@ -26308,7 +25765,8 @@ static const struct builtin_description bdesc_special_args[] =
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movdqu, "__builtin_ia32_storedqu", IX86_BUILTIN_STOREDQU, UNKNOWN, (int) VOID_FTYPE_PCHAR_V16QI },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movntv2df, "__builtin_ia32_movntpd", IX86_BUILTIN_MOVNTPD, UNKNOWN, (int) VOID_FTYPE_PDOUBLE_V2DF },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movntv2di, "__builtin_ia32_movntdq", IX86_BUILTIN_MOVNTDQ, UNKNOWN, (int) VOID_FTYPE_PV2DI_V2DI },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movntsi, "__builtin_ia32_movnti", IX86_BUILTIN_MOVNTI, UNKNOWN, (int) VOID_FTYPE_PINT_INT },
+ { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movntisi, "__builtin_ia32_movnti", IX86_BUILTIN_MOVNTI, UNKNOWN, (int) VOID_FTYPE_PINT_INT },
+ { OPTION_MASK_ISA_SSE2 | OPTION_MASK_ISA_64BIT, CODE_FOR_sse2_movntidi, "__builtin_ia32_movnti64", IX86_BUILTIN_MOVNTI64, UNKNOWN, (int) VOID_FTYPE_PLONGLONG_LONGLONG },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movupd, "__builtin_ia32_loadupd", IX86_BUILTIN_LOADUPD, UNKNOWN, (int) V2DF_FTYPE_PCDOUBLE },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movdqu, "__builtin_ia32_loaddqu", IX86_BUILTIN_LOADDQU, UNKNOWN, (int) V16QI_FTYPE_PCCHAR },
@@ -26856,14 +26314,22 @@ static const struct builtin_description bdesc_args[] =
{ OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_truncpd", IX86_BUILTIN_TRUNCPD, (enum rtx_code) ROUND_TRUNC, (int) V2DF_FTYPE_V2DF_ROUND },
{ OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_rintpd", IX86_BUILTIN_RINTPD, (enum rtx_code) ROUND_MXCSR, (int) V2DF_FTYPE_V2DF_ROUND },
+ { OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundpd_vec_pack_sfix, "__builtin_ia32_floorpd_vec_pack_sfix", IX86_BUILTIN_FLOORPD_VEC_PACK_SFIX, (enum rtx_code) ROUND_FLOOR, (int) V4SI_FTYPE_V2DF_V2DF_ROUND },
+ { OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundpd_vec_pack_sfix, "__builtin_ia32_ceilpd_vec_pack_sfix", IX86_BUILTIN_CEILPD_VEC_PACK_SFIX, (enum rtx_code) ROUND_CEIL, (int) V4SI_FTYPE_V2DF_V2DF_ROUND },
+
{ OPTION_MASK_ISA_ROUND, CODE_FOR_roundv2df2, "__builtin_ia32_roundpd_az", IX86_BUILTIN_ROUNDPD_AZ, UNKNOWN, (int) V2DF_FTYPE_V2DF },
+ { OPTION_MASK_ISA_ROUND, CODE_FOR_roundv2df2_vec_pack_sfix, "__builtin_ia32_roundpd_az_vec_pack_sfix", IX86_BUILTIN_ROUNDPD_AZ_VEC_PACK_SFIX, UNKNOWN, (int) V4SI_FTYPE_V2DF_V2DF },
{ OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundps, "__builtin_ia32_floorps", IX86_BUILTIN_FLOORPS, (enum rtx_code) ROUND_FLOOR, (int) V4SF_FTYPE_V4SF_ROUND },
{ OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundps, "__builtin_ia32_ceilps", IX86_BUILTIN_CEILPS, (enum rtx_code) ROUND_CEIL, (int) V4SF_FTYPE_V4SF_ROUND },
{ OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundps, "__builtin_ia32_truncps", IX86_BUILTIN_TRUNCPS, (enum rtx_code) ROUND_TRUNC, (int) V4SF_FTYPE_V4SF_ROUND },
{ OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundps, "__builtin_ia32_rintps", IX86_BUILTIN_RINTPS, (enum rtx_code) ROUND_MXCSR, (int) V4SF_FTYPE_V4SF_ROUND },
+ { OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundps_sfix, "__builtin_ia32_floorps_sfix", IX86_BUILTIN_FLOORPS_SFIX, (enum rtx_code) ROUND_FLOOR, (int) V4SI_FTYPE_V4SF_ROUND },
+ { OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundps_sfix, "__builtin_ia32_ceilps_sfix", IX86_BUILTIN_CEILPS_SFIX, (enum rtx_code) ROUND_CEIL, (int) V4SI_FTYPE_V4SF_ROUND },
+
{ OPTION_MASK_ISA_ROUND, CODE_FOR_roundv4sf2, "__builtin_ia32_roundps_az", IX86_BUILTIN_ROUNDPS_AZ, UNKNOWN, (int) V4SF_FTYPE_V4SF },
+ { OPTION_MASK_ISA_ROUND, CODE_FOR_roundv4sf2_sfix, "__builtin_ia32_roundps_az_sfix", IX86_BUILTIN_ROUNDPS_AZ_SFIX, UNKNOWN, (int) V4SI_FTYPE_V4SF },
{ OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_ptest, "__builtin_ia32_ptestz128", IX86_BUILTIN_PTESTZ, EQ, (int) INT_FTYPE_V2DI_V2DI_PTEST },
{ OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_ptest, "__builtin_ia32_ptestc128", IX86_BUILTIN_PTESTC, LTU, (int) INT_FTYPE_V2DI_V2DI_PTEST },
@@ -26983,13 +26449,21 @@ static const struct builtin_description bdesc_args[] =
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_roundpd256, "__builtin_ia32_rintpd256", IX86_BUILTIN_RINTPD256, (enum rtx_code) ROUND_MXCSR, (int) V4DF_FTYPE_V4DF_ROUND },
{ OPTION_MASK_ISA_AVX, CODE_FOR_roundv4df2, "__builtin_ia32_roundpd_az256", IX86_BUILTIN_ROUNDPD_AZ256, UNKNOWN, (int) V4DF_FTYPE_V4DF },
+ { OPTION_MASK_ISA_AVX, CODE_FOR_roundv4df2_vec_pack_sfix, "__builtin_ia32_roundpd_az_vec_pack_sfix256", IX86_BUILTIN_ROUNDPD_AZ_VEC_PACK_SFIX256, UNKNOWN, (int) V8SI_FTYPE_V4DF_V4DF },
+
+ { OPTION_MASK_ISA_AVX, CODE_FOR_avx_roundpd_vec_pack_sfix256, "__builtin_ia32_floorpd_vec_pack_sfix256", IX86_BUILTIN_FLOORPD_VEC_PACK_SFIX256, (enum rtx_code) ROUND_FLOOR, (int) V8SI_FTYPE_V4DF_V4DF_ROUND },
+ { OPTION_MASK_ISA_AVX, CODE_FOR_avx_roundpd_vec_pack_sfix256, "__builtin_ia32_ceilpd_vec_pack_sfix256", IX86_BUILTIN_CEILPD_VEC_PACK_SFIX256, (enum rtx_code) ROUND_CEIL, (int) V8SI_FTYPE_V4DF_V4DF_ROUND },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_roundps256, "__builtin_ia32_floorps256", IX86_BUILTIN_FLOORPS256, (enum rtx_code) ROUND_FLOOR, (int) V8SF_FTYPE_V8SF_ROUND },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_roundps256, "__builtin_ia32_ceilps256", IX86_BUILTIN_CEILPS256, (enum rtx_code) ROUND_CEIL, (int) V8SF_FTYPE_V8SF_ROUND },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_roundps256, "__builtin_ia32_truncps256", IX86_BUILTIN_TRUNCPS256, (enum rtx_code) ROUND_TRUNC, (int) V8SF_FTYPE_V8SF_ROUND },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_roundps256, "__builtin_ia32_rintps256", IX86_BUILTIN_RINTPS256, (enum rtx_code) ROUND_MXCSR, (int) V8SF_FTYPE_V8SF_ROUND },
+ { OPTION_MASK_ISA_AVX, CODE_FOR_avx_roundps_sfix256, "__builtin_ia32_floorps_sfix256", IX86_BUILTIN_FLOORPS_SFIX256, (enum rtx_code) ROUND_FLOOR, (int) V8SI_FTYPE_V8SF_ROUND },
+ { OPTION_MASK_ISA_AVX, CODE_FOR_avx_roundps_sfix256, "__builtin_ia32_ceilps_sfix256", IX86_BUILTIN_CEILPS_SFIX256, (enum rtx_code) ROUND_CEIL, (int) V8SI_FTYPE_V8SF_ROUND },
+
{ OPTION_MASK_ISA_AVX, CODE_FOR_roundv8sf2, "__builtin_ia32_roundps_az256", IX86_BUILTIN_ROUNDPS_AZ256, UNKNOWN, (int) V8SF_FTYPE_V8SF },
+ { OPTION_MASK_ISA_AVX, CODE_FOR_roundv8sf2_sfix, "__builtin_ia32_roundps_az_sfix256", IX86_BUILTIN_ROUNDPS_AZ_SFIX256, UNKNOWN, (int) V8SI_FTYPE_V8SF },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_unpckhpd256, "__builtin_ia32_unpckhpd256", IX86_BUILTIN_UNPCKHPD256, UNKNOWN, (int) V4DF_FTYPE_V4DF_V4DF },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_unpcklpd256, "__builtin_ia32_unpcklpd256", IX86_BUILTIN_UNPCKLPD256, UNKNOWN, (int) V4DF_FTYPE_V4DF_V4DF },
@@ -28430,7 +27904,7 @@ ix86_expand_sse_comi (const struct builtin_description *d, tree exp,
return SUBREG_REG (target);
}
-/* Subroutine of ix86_expand_args_builtin to take care of round insns. */
+/* Subroutines of ix86_expand_args_builtin to take care of round insns. */
static rtx
ix86_expand_sse_round (const struct builtin_description *d, tree exp,
@@ -28463,6 +27937,44 @@ ix86_expand_sse_round (const struct builtin_description *d, tree exp,
return target;
}
+static rtx
+ix86_expand_sse_round_vec_pack_sfix (const struct builtin_description *d,
+ tree exp, rtx target)
+{
+ rtx pat;
+ tree arg0 = CALL_EXPR_ARG (exp, 0);
+ tree arg1 = CALL_EXPR_ARG (exp, 1);
+ rtx op0 = expand_normal (arg0);
+ rtx op1 = expand_normal (arg1);
+ rtx op2;
+ enum machine_mode tmode = insn_data[d->icode].operand[0].mode;
+ enum machine_mode mode0 = insn_data[d->icode].operand[1].mode;
+ enum machine_mode mode1 = insn_data[d->icode].operand[2].mode;
+
+ if (optimize || target == 0
+ || GET_MODE (target) != tmode
+ || !insn_data[d->icode].operand[0].predicate (target, tmode))
+ target = gen_reg_rtx (tmode);
+
+ op0 = safe_vector_operand (op0, mode0);
+ op1 = safe_vector_operand (op1, mode1);
+
+ if ((optimize && !register_operand (op0, mode0))
+ || !insn_data[d->icode].operand[0].predicate (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+ if ((optimize && !register_operand (op1, mode1))
+ || !insn_data[d->icode].operand[1].predicate (op1, mode1))
+ op1 = copy_to_mode_reg (mode1, op1);
+
+ op2 = GEN_INT (d->comparison);
+
+ pat = GEN_FCN (d->icode) (target, op0, op1, op2);
+ if (! pat)
+ return 0;
+ emit_insn (pat);
+ return target;
+}
+
/* Subroutine of ix86_expand_builtin to take care of ptest insns. */
static rtx
@@ -28736,7 +28248,12 @@ ix86_expand_args_builtin (const struct builtin_description *d,
case V4DF_FTYPE_V4DF_ROUND:
case V4SF_FTYPE_V4SF_ROUND:
case V8SF_FTYPE_V8SF_ROUND:
+ case V4SI_FTYPE_V4SF_ROUND:
+ case V8SI_FTYPE_V8SF_ROUND:
return ix86_expand_sse_round (d, exp, target);
+ case V4SI_FTYPE_V2DF_V2DF_ROUND:
+ case V8SI_FTYPE_V4DF_V4DF_ROUND:
+ return ix86_expand_sse_round_vec_pack_sfix (d, exp, target);
case INT_FTYPE_V8SF_V8SF_PTEST:
case INT_FTYPE_V4DI_V4DI_PTEST:
case INT_FTYPE_V4DF_V4DF_PTEST:
@@ -29053,15 +28570,22 @@ ix86_expand_args_builtin (const struct builtin_description *d,
error ("the last argument must be an 1-bit immediate");
return const0_rtx;
- case CODE_FOR_sse4_1_roundpd:
- case CODE_FOR_sse4_1_roundps:
case CODE_FOR_sse4_1_roundsd:
case CODE_FOR_sse4_1_roundss:
+
+ case CODE_FOR_sse4_1_roundpd:
+ case CODE_FOR_sse4_1_roundps:
+ case CODE_FOR_avx_roundpd256:
+ case CODE_FOR_avx_roundps256:
+
+ case CODE_FOR_sse4_1_roundpd_vec_pack_sfix:
+ case CODE_FOR_sse4_1_roundps_sfix:
+ case CODE_FOR_avx_roundpd_vec_pack_sfix256:
+ case CODE_FOR_avx_roundps_sfix256:
+
case CODE_FOR_sse4_1_blendps:
case CODE_FOR_avx_blendpd256:
case CODE_FOR_avx_vpermilv4df:
- case CODE_FOR_avx_roundpd256:
- case CODE_FOR_avx_roundps256:
error ("the last argument must be a 4-bit immediate");
return const0_rtx;
@@ -29228,6 +28752,7 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
case VOID_FTYPE_PFLOAT_V4SF:
case VOID_FTYPE_PDOUBLE_V4DF:
case VOID_FTYPE_PDOUBLE_V2DF:
+ case VOID_FTYPE_PLONGLONG_LONGLONG:
case VOID_FTYPE_PULONGLONG_ULONGLONG:
case VOID_FTYPE_PINT_INT:
nargs = 1;
@@ -29829,7 +29354,7 @@ rdrand_step:
icode = CODE_FOR_avx2_gatherdiv8sf;
goto gather_gen;
case IX86_BUILTIN_GATHERALTSIV4DI:
- icode = CODE_FOR_avx2_gathersiv4df;
+ icode = CODE_FOR_avx2_gathersiv4di;
goto gather_gen;
case IX86_BUILTIN_GATHERALTDIV8SI:
icode = CODE_FOR_avx2_gatherdiv8si;
@@ -30087,6 +29612,70 @@ ix86_builtin_vectorized_function (tree fndecl, tree type_out,
}
break;
+ case BUILT_IN_IFLOOR:
+ case BUILT_IN_LFLOOR:
+ case BUILT_IN_LLFLOOR:
+ /* The round insn does not trap on denormals. */
+ if (flag_trapping_math || !TARGET_ROUND)
+ break;
+
+ if (out_mode == SImode && in_mode == DFmode)
+ {
+ if (out_n == 4 && in_n == 2)
+ return ix86_builtins[IX86_BUILTIN_FLOORPD_VEC_PACK_SFIX];
+ else if (out_n == 8 && in_n == 4)
+ return ix86_builtins[IX86_BUILTIN_FLOORPD_VEC_PACK_SFIX256];
+ }
+ break;
+
+ case BUILT_IN_IFLOORF:
+ case BUILT_IN_LFLOORF:
+ case BUILT_IN_LLFLOORF:
+ /* The round insn does not trap on denormals. */
+ if (flag_trapping_math || !TARGET_ROUND)
+ break;
+
+ if (out_mode == SImode && in_mode == SFmode)
+ {
+ if (out_n == 4 && in_n == 4)
+ return ix86_builtins[IX86_BUILTIN_FLOORPS_SFIX];
+ else if (out_n == 8 && in_n == 8)
+ return ix86_builtins[IX86_BUILTIN_FLOORPS_SFIX256];
+ }
+ break;
+
+ case BUILT_IN_ICEIL:
+ case BUILT_IN_LCEIL:
+ case BUILT_IN_LLCEIL:
+ /* The round insn does not trap on denormals. */
+ if (flag_trapping_math || !TARGET_ROUND)
+ break;
+
+ if (out_mode == SImode && in_mode == DFmode)
+ {
+ if (out_n == 4 && in_n == 2)
+ return ix86_builtins[IX86_BUILTIN_CEILPD_VEC_PACK_SFIX];
+ else if (out_n == 8 && in_n == 4)
+ return ix86_builtins[IX86_BUILTIN_CEILPD_VEC_PACK_SFIX256];
+ }
+ break;
+
+ case BUILT_IN_ICEILF:
+ case BUILT_IN_LCEILF:
+ case BUILT_IN_LLCEILF:
+ /* The round insn does not trap on denormals. */
+ if (flag_trapping_math || !TARGET_ROUND)
+ break;
+
+ if (out_mode == SImode && in_mode == SFmode)
+ {
+ if (out_n == 4 && in_n == 4)
+ return ix86_builtins[IX86_BUILTIN_CEILPS_SFIX];
+ else if (out_n == 8 && in_n == 8)
+ return ix86_builtins[IX86_BUILTIN_CEILPS_SFIX256];
+ }
+ break;
+
case BUILT_IN_IRINT:
case BUILT_IN_LRINT:
case BUILT_IN_LLRINT:
@@ -30111,6 +29700,38 @@ ix86_builtin_vectorized_function (tree fndecl, tree type_out,
}
break;
+ case BUILT_IN_IROUND:
+ case BUILT_IN_LROUND:
+ case BUILT_IN_LLROUND:
+ /* The round insn does not trap on denormals. */
+ if (flag_trapping_math || !TARGET_ROUND)
+ break;
+
+ if (out_mode == SImode && in_mode == DFmode)
+ {
+ if (out_n == 4 && in_n == 2)
+ return ix86_builtins[IX86_BUILTIN_ROUNDPD_AZ_VEC_PACK_SFIX];
+ else if (out_n == 8 && in_n == 4)
+ return ix86_builtins[IX86_BUILTIN_ROUNDPD_AZ_VEC_PACK_SFIX256];
+ }
+ break;
+
+ case BUILT_IN_IROUNDF:
+ case BUILT_IN_LROUNDF:
+ case BUILT_IN_LLROUNDF:
+ /* The round insn does not trap on denormals. */
+ if (flag_trapping_math || !TARGET_ROUND)
+ break;
+
+ if (out_mode == SImode && in_mode == SFmode)
+ {
+ if (out_n == 4 && in_n == 4)
+ return ix86_builtins[IX86_BUILTIN_ROUNDPS_AZ_SFIX];
+ else if (out_n == 8 && in_n == 8)
+ return ix86_builtins[IX86_BUILTIN_ROUNDPS_AZ_SFIX256];
+ }
+ break;
+
case BUILT_IN_COPYSIGN:
if (out_mode == DFmode && in_mode == DFmode)
{
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index b10a13cad8a..7721c465832 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -159,12 +159,8 @@ struct processor_costs {
const int fchs; /* cost of FCHS instruction. */
const int fsqrt; /* cost of FSQRT instruction. */
/* Specify what algorithm
- to use for stringops on unknown size.
- First index is used to specify whether
- alignment is known or not.
- Second - to specify whether 32 or 64 bits
- are used. */
- struct stringop_algs memcpy[2][2], memset[2][2];
+ to use for stringops on unknown size. */
+ struct stringop_algs memcpy[2], memset[2];
const int scalar_stmt_cost; /* Cost of any scalar operation, excluding
load and store. */
const int scalar_load_cost; /* Cost of scalar load. */
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index bc602532304..fa306ba79d8 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -62,8 +62,6 @@
;; ; -- print a semicolon (after prefixes due to bug in older gas).
;; @ -- print a segment register of thread base pointer load
-;; UNSPEC usage:
-
(define_c_enum "unspec" [
;; Relocation specifiers
UNSPEC_GOT
@@ -108,6 +106,7 @@
UNSPEC_LD_MPIC ; load_macho_picbase
UNSPEC_TRUNC_NOOP
UNSPEC_DIV_ALREADY_SPLIT
+ UNSPEC_MS_TO_SYSV_CALL
UNSPEC_CALL_NEEDS_VZEROUPPER
UNSPEC_PAUSE
@@ -115,21 +114,9 @@
UNSPEC_FIX_NOTRUNC
UNSPEC_MASKMOV
UNSPEC_MOVMSK
- UNSPEC_MOVNT
- UNSPEC_MOVU
UNSPEC_RCP
UNSPEC_RSQRT
- UNSPEC_SFENCE
- UNSPEC_PFRCP
- UNSPEC_PFRCPIT1
- UNSPEC_PFRCPIT2
- UNSPEC_PFRSQRT
- UNSPEC_PFRSQIT1
- UNSPEC_MFENCE
- UNSPEC_LFENCE
UNSPEC_PSADBW
- UNSPEC_LDDQU
- UNSPEC_MS_TO_SYSV_CALL
;; Generic math support
UNSPEC_COPYSIGN
@@ -177,105 +164,32 @@
UNSPEC_SP_TLS_SET
UNSPEC_SP_TLS_TEST
- ;; SSSE3
- UNSPEC_PSHUFB
- UNSPEC_PSIGN
- UNSPEC_PALIGNR
-
- ;; For SSE4A support
- UNSPEC_EXTRQI
- UNSPEC_EXTRQ
- UNSPEC_INSERTQI
- UNSPEC_INSERTQ
-
- ;; For SSE4.1 support
- UNSPEC_BLENDV
- UNSPEC_INSERTPS
- UNSPEC_DP
- UNSPEC_MOVNTDQA
- UNSPEC_MPSADBW
- UNSPEC_PHMINPOSUW
- UNSPEC_PTEST
+ ;; For ROUND support
UNSPEC_ROUND
- ;; For SSE4.2 support
+ ;; For CRC32 support
UNSPEC_CRC32
- UNSPEC_PCMPESTR
- UNSPEC_PCMPISTR
-
- ;; For FMA4 support
- UNSPEC_FMADDSUB
- UNSPEC_XOP_UNSIGNED_CMP
- UNSPEC_XOP_TRUEFALSE
- UNSPEC_XOP_PERMUTE
- UNSPEC_FRCZ
-
- ;; For AES support
- UNSPEC_AESENC
- UNSPEC_AESENCLAST
- UNSPEC_AESDEC
- UNSPEC_AESDECLAST
- UNSPEC_AESIMC
- UNSPEC_AESKEYGENASSIST
-
- ;; For PCLMUL support
- UNSPEC_PCLMUL
-
- ;; For AVX support
- UNSPEC_PCMP
- UNSPEC_VPERMIL
- UNSPEC_VPERMIL2
- UNSPEC_VPERMIL2F128
- UNSPEC_CAST
- UNSPEC_VTESTP
- UNSPEC_VCVTPH2PS
- UNSPEC_VCVTPS2PH
-
- ;; For AVX2 support
- UNSPEC_VPERMSI
- UNSPEC_VPERMDF
- UNSPEC_VPERMSF
- UNSPEC_VPERMTI
- UNSPEC_GATHER
- UNSPEC_VSIBADDR
-
- ;; For BMI support
- UNSPEC_BEXTR
;; For RDRAND support
UNSPEC_RDRAND
+ ;; For BMI support
+ UNSPEC_BEXTR
+
;; For BMI2 support
UNSPEC_PDEP
UNSPEC_PEXT
-
- ;; For __atomic support
- UNSPEC_MOVA
])
(define_c_enum "unspecv" [
UNSPECV_BLOCKAGE
UNSPECV_STACK_PROBE
UNSPECV_PROBE_STACK_RANGE
- UNSPECV_EMMS
- UNSPECV_LDMXCSR
- UNSPECV_STMXCSR
- UNSPECV_FEMMS
- UNSPECV_CLFLUSH
UNSPECV_ALIGN
- UNSPECV_MONITOR
- UNSPECV_MWAIT
- UNSPECV_CMPXCHG_1
- UNSPECV_CMPXCHG_2
- UNSPECV_CMPXCHG_3
- UNSPECV_CMPXCHG_4
- UNSPECV_XCHG
- UNSPECV_LOCK
UNSPECV_PROLOGUE_USE
+ UNSPECV_SPLIT_STACK_RETURN
UNSPECV_CLD
UNSPECV_NOPS
- UNSPECV_VZEROALL
- UNSPECV_VZEROUPPER
UNSPECV_RDTSC
UNSPECV_RDTSCP
UNSPECV_RDPMC
@@ -287,7 +201,6 @@
UNSPECV_RDGSBASE
UNSPECV_WRFSBASE
UNSPECV_WRGSBASE
- UNSPECV_SPLIT_STACK_RETURN
])
;; Constants to represent rounding modes in the ROUND instruction
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index e797362d2dc..6c516e7b869 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -324,9 +324,6 @@ Enum(stringop_alg) String(loop) Value(loop)
EnumValue
Enum(stringop_alg) String(unrolled_loop) Value(unrolled_loop)
-EnumValue
-Enum(stringop_alg) String(sse_loop) Value(sse_loop)
-
mtls-dialect=
Target RejectNegative Joined Var(ix86_tls_dialect) Enum(tls_dialect) Init(TLS_DIALECT_GNU)
Use given thread-local storage dialect
diff --git a/gcc/config/i386/i386elf.h b/gcc/config/i386/i386elf.h
index 1b942cba914..1bf3feb7479 100644
--- a/gcc/config/i386/i386elf.h
+++ b/gcc/config/i386/i386elf.h
@@ -20,10 +20,6 @@ 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/>. */
-/* Use stabs instead of DWARF debug format. */
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-
/* The ELF ABI for the i386 says that records and unions are returned
in memory. */
@@ -50,7 +46,7 @@ along with GCC; see the file COPYING3. If not see
generated assembly code more compact (and thus faster to assemble)
as well as more readable. Note that if we find subparts of the
character sequence which end with NUL (and which are shorter than
- STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
+ ELF_STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
#undef ASM_OUTPUT_ASCII
#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH) \
@@ -70,7 +66,7 @@ along with GCC; see the file COPYING3. If not see
} \
for (p = _ascii_bytes; p < limit && *p != '\0'; p++) \
continue; \
- if (p < limit && (p - _ascii_bytes) <= (long) STRING_LIMIT) \
+ if (p < limit && (p - _ascii_bytes) <= (long) ELF_STRING_LIMIT) \
{ \
if (bytes_in_chunk > 0) \
{ \
diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md
index f76834e5ab2..e859b9f1bed 100644
--- a/gcc/config/i386/mmx.md
+++ b/gcc/config/i386/mmx.md
@@ -30,6 +30,20 @@
;; means that we should never use any of these patterns except at the
;; direction of the user via a builtin.
+(define_c_enum "unspec" [
+ UNSPEC_MOVNTQ
+ UNSPEC_PFRCP
+ UNSPEC_PFRCPIT1
+ UNSPEC_PFRCPIT2
+ UNSPEC_PFRSQRT
+ UNSPEC_PFRSQIT1
+])
+
+(define_c_enum "unspecv" [
+ UNSPECV_EMMS
+ UNSPECV_FEMMS
+])
+
;; 8 byte integral modes handled by MMX (and by extension, SSE)
(define_mode_iterator MMXMODEI [V8QI V4HI V2SI])
(define_mode_iterator MMXMODEI8 [V8QI V4HI V2SI V1DI])
@@ -329,10 +343,10 @@
DONE;
})
-(define_insn "sse_movntdi"
+(define_insn "sse_movntq"
[(set (match_operand:DI 0 "memory_operand" "=m")
(unspec:DI [(match_operand:DI 1 "register_operand" "y")]
- UNSPEC_MOVNT))]
+ UNSPEC_MOVNTQ))]
"TARGET_SSE || TARGET_3DNOW_A"
"movntq\t{%1, %0|%0, %1}"
[(set_attr "type" "mmxmov")
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 4938abffce5..8c434b79bb8 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -18,6 +18,85 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
+(define_c_enum "unspec" [
+ ;; SSE
+ UNSPEC_MOVNT
+ UNSPEC_MOVU
+
+ ;; SSE3
+ UNSPEC_LDDQU
+
+ ;; SSSE3
+ UNSPEC_PSHUFB
+ UNSPEC_PSIGN
+ UNSPEC_PALIGNR
+
+ ;; For SSE4A support
+ UNSPEC_EXTRQI
+ UNSPEC_EXTRQ
+ UNSPEC_INSERTQI
+ UNSPEC_INSERTQ
+
+ ;; For SSE4.1 support
+ UNSPEC_BLENDV
+ UNSPEC_INSERTPS
+ UNSPEC_DP
+ UNSPEC_MOVNTDQA
+ UNSPEC_MPSADBW
+ UNSPEC_PHMINPOSUW
+ UNSPEC_PTEST
+
+ ;; For SSE4.2 support
+ UNSPEC_PCMPESTR
+ UNSPEC_PCMPISTR
+
+ ;; For FMA4 support
+ UNSPEC_FMADDSUB
+ UNSPEC_XOP_UNSIGNED_CMP
+ UNSPEC_XOP_TRUEFALSE
+ UNSPEC_XOP_PERMUTE
+ UNSPEC_FRCZ
+
+ ;; For AES support
+ UNSPEC_AESENC
+ UNSPEC_AESENCLAST
+ UNSPEC_AESDEC
+ UNSPEC_AESDECLAST
+ UNSPEC_AESIMC
+ UNSPEC_AESKEYGENASSIST
+
+ ;; For PCLMUL support
+ UNSPEC_PCLMUL
+
+ ;; For AVX support
+ UNSPEC_PCMP
+ UNSPEC_VPERMIL
+ UNSPEC_VPERMIL2
+ UNSPEC_VPERMIL2F128
+ UNSPEC_CAST
+ UNSPEC_VTESTP
+ UNSPEC_VCVTPH2PS
+ UNSPEC_VCVTPS2PH
+
+ ;; For AVX2 support
+ UNSPEC_VPERMSI
+ UNSPEC_VPERMDF
+ UNSPEC_VPERMSF
+ UNSPEC_VPERMTI
+ UNSPEC_GATHER
+ UNSPEC_VSIBADDR
+])
+
+(define_c_enum "unspecv" [
+ UNSPECV_LDMXCSR
+ UNSPECV_STMXCSR
+ UNSPECV_CLFLUSH
+ UNSPECV_MONITOR
+ UNSPECV_MWAIT
+ UNSPECV_VZEROALL
+ UNSPECV_VZEROUPPER
+])
+
;; All vector modes including V?TImode, used in move patterns.
(define_mode_iterator V16
[(V32QI "TARGET_AVX") V16QI
@@ -573,15 +652,15 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "<sseinsnmode>")])
-(define_insn "sse2_movntsi"
- [(set (match_operand:SI 0 "memory_operand" "=m")
- (unspec:SI [(match_operand:SI 1 "register_operand" "r")]
- UNSPEC_MOVNT))]
+(define_insn "sse2_movnti<mode>"
+ [(set (match_operand:SWI48 0 "memory_operand" "=m")
+ (unspec:SWI48 [(match_operand:SWI48 1 "register_operand" "r")]
+ UNSPEC_MOVNT))]
"TARGET_SSE2"
"movnti\t{%1, %0|%0, %1}"
[(set_attr "type" "ssemov")
(set_attr "prefix_data16" "0")
- (set_attr "mode" "V2DF")])
+ (set_attr "mode" "<MODE>")])
(define_insn "<sse>_movnt<mode>"
[(set (match_operand:VF 0 "memory_operand" "=m")
@@ -614,8 +693,9 @@
;; Modes handled by storent patterns.
(define_mode_iterator STORENT_MODE
- [(SI "TARGET_SSE2") (SF "TARGET_SSE4A") (DF "TARGET_SSE4A")
- (V2DI "TARGET_SSE2")
+ [(DI "TARGET_SSE2 && TARGET_64BIT") (SI "TARGET_SSE2")
+ (SF "TARGET_SSE4A") (DF "TARGET_SSE4A")
+ (V4DI "TARGET_AVX") (V2DI "TARGET_SSE2")
(V8SF "TARGET_AVX") V4SF
(V4DF "TARGET_AVX") (V2DF "TARGET_SSE2")])
@@ -3038,14 +3118,25 @@
(match_operand:V2DF 2 "nonimmediate_operand" "")]
"TARGET_SSE2"
{
- rtx r1, r2;
+ rtx tmp0, tmp1;
- r1 = gen_reg_rtx (V4SFmode);
- r2 = gen_reg_rtx (V4SFmode);
+ if (TARGET_AVX && !TARGET_PREFER_AVX128)
+ {
+ tmp0 = gen_reg_rtx (V4DFmode);
+ tmp1 = force_reg (V2DFmode, operands[1]);
- emit_insn (gen_sse2_cvtpd2ps (r1, operands[1]));
- emit_insn (gen_sse2_cvtpd2ps (r2, operands[2]));
- emit_insn (gen_sse_movlhps (operands[0], r1, r2));
+ emit_insn (gen_avx_vec_concatv4df (tmp0, tmp1, operands[2]));
+ emit_insn (gen_avx_cvtpd2ps256 (operands[0], tmp0));
+ }
+ else
+ {
+ tmp0 = gen_reg_rtx (V4SFmode);
+ tmp1 = gen_reg_rtx (V4SFmode);
+
+ emit_insn (gen_sse2_cvtpd2ps (tmp0, operands[1]));
+ emit_insn (gen_sse2_cvtpd2ps (tmp1, operands[2]));
+ emit_insn (gen_sse_movlhps (operands[0], tmp0, tmp1));
+ }
DONE;
})
@@ -3057,12 +3148,12 @@
{
rtx r1, r2;
- r1 = gen_reg_rtx (V8SImode);
- r2 = gen_reg_rtx (V8SImode);
+ r1 = gen_reg_rtx (V4SImode);
+ r2 = gen_reg_rtx (V4SImode);
- 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)));
+ emit_insn (gen_fix_truncv4dfv4si2 (r1, operands[1]));
+ emit_insn (gen_fix_truncv4dfv4si2 (r2, operands[2]));
+ emit_insn (gen_avx_vec_concatv8si (operands[0], r1, r2));
DONE;
})
@@ -3072,16 +3163,28 @@
(match_operand:V2DF 2 "nonimmediate_operand" "")]
"TARGET_SSE2"
{
- rtx r1, r2;
+ rtx tmp0, tmp1;
- r1 = gen_reg_rtx (V4SImode);
- r2 = gen_reg_rtx (V4SImode);
+ if (TARGET_AVX && !TARGET_PREFER_AVX128)
+ {
+ tmp0 = gen_reg_rtx (V4DFmode);
+ tmp1 = force_reg (V2DFmode, operands[1]);
- emit_insn (gen_sse2_cvttpd2dq (r1, operands[1]));
- emit_insn (gen_sse2_cvttpd2dq (r2, operands[2]));
- emit_insn (gen_vec_interleave_lowv2di (gen_lowpart (V2DImode, operands[0]),
- gen_lowpart (V2DImode, r1),
- gen_lowpart (V2DImode, r2)));
+ emit_insn (gen_avx_vec_concatv4df (tmp0, tmp1, operands[2]));
+ emit_insn (gen_fix_truncv4dfv4si2 (operands[0], tmp0));
+ }
+ else
+ {
+ tmp0 = gen_reg_rtx (V4SImode);
+ tmp1 = gen_reg_rtx (V4SImode);
+
+ emit_insn (gen_sse2_cvttpd2dq (tmp0, operands[1]));
+ emit_insn (gen_sse2_cvttpd2dq (tmp1, operands[2]));
+ emit_insn
+ (gen_vec_interleave_lowv2di (gen_lowpart (V2DImode, operands[0]),
+ gen_lowpart (V2DImode, tmp0),
+ gen_lowpart (V2DImode, tmp1)));
+ }
DONE;
})
@@ -3126,12 +3229,12 @@
{
rtx r1, r2;
- r1 = gen_reg_rtx (V8SImode);
- r2 = gen_reg_rtx (V8SImode);
+ r1 = gen_reg_rtx (V4SImode);
+ r2 = gen_reg_rtx (V4SImode);
- 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)));
+ emit_insn (gen_avx_cvtpd2dq256 (r1, operands[1]));
+ emit_insn (gen_avx_cvtpd2dq256 (r2, operands[2]));
+ emit_insn (gen_avx_vec_concatv8si (operands[0], r1, r2));
DONE;
})
@@ -3141,16 +3244,28 @@
(match_operand:V2DF 2 "nonimmediate_operand" "")]
"TARGET_SSE2"
{
- rtx r1, r2;
+ rtx tmp0, tmp1;
- r1 = gen_reg_rtx (V4SImode);
- r2 = gen_reg_rtx (V4SImode);
+ if (TARGET_AVX && !TARGET_PREFER_AVX128)
+ {
+ tmp0 = gen_reg_rtx (V4DFmode);
+ tmp1 = force_reg (V2DFmode, operands[1]);
- emit_insn (gen_sse2_cvtpd2dq (r1, operands[1]));
- emit_insn (gen_sse2_cvtpd2dq (r2, operands[2]));
- emit_insn (gen_vec_interleave_lowv2di (gen_lowpart (V2DImode, operands[0]),
- gen_lowpart (V2DImode, r1),
- gen_lowpart (V2DImode, r2)));
+ emit_insn (gen_avx_vec_concatv4df (tmp0, tmp1, operands[2]));
+ emit_insn (gen_avx_cvtpd2dq256 (operands[0], tmp0));
+ }
+ else
+ {
+ tmp0 = gen_reg_rtx (V4SImode);
+ tmp1 = gen_reg_rtx (V4SImode);
+
+ emit_insn (gen_sse2_cvtpd2dq (tmp0, operands[1]));
+ emit_insn (gen_sse2_cvtpd2dq (tmp1, operands[2]));
+ emit_insn
+ (gen_vec_interleave_lowv2di (gen_lowpart (V2DImode, operands[0]),
+ gen_lowpart (V2DImode, tmp0),
+ gen_lowpart (V2DImode, tmp1)));
+ }
DONE;
})
@@ -7501,16 +7616,6 @@
(set_attr "prefix" "maybe_vex,orig,vex,maybe_vex,orig,orig")
(set_attr "mode" "V2SF,TI,TI,TI,V4SF,V2SF")])
-(define_expand "vec_dupv4si"
- [(set (match_operand:V4SI 0 "register_operand" "")
- (vec_duplicate:V4SI
- (match_operand:SI 1 "nonimmediate_operand" "")))]
- "TARGET_SSE"
-{
- if (!TARGET_AVX)
- operands[1] = force_reg (V4SImode, operands[1]);
-})
-
(define_insn "*vec_dupv4si"
[(set (match_operand:V4SI 0 "register_operand" "=x,x,x")
(vec_duplicate:V4SI
@@ -7527,16 +7632,6 @@
(set_attr "prefix" "maybe_vex,vex,orig")
(set_attr "mode" "TI,V4SF,V4SF")])
-(define_expand "vec_dupv2di"
- [(set (match_operand:V2DI 0 "register_operand" "")
- (vec_duplicate:V2DI
- (match_operand:DI 1 "nonimmediate_operand" "")))]
- "TARGET_SSE"
-{
- if (!TARGET_AVX)
- operands[1] = force_reg (V2DImode, operands[1]);
-})
-
(define_insn "*vec_dupv2di"
[(set (match_operand:V2DI 0 "register_operand" "=x,x,x,x")
(vec_duplicate:V2DI
@@ -8005,25 +8100,6 @@
(set_attr "prefix" "maybe_vex")
(set_attr "memory" "store")])
-(define_expand "sse_sfence"
- [(set (match_dup 0)
- (unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))]
- "TARGET_SSE || TARGET_3DNOW_A"
-{
- operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
- MEM_VOLATILE_P (operands[0]) = 1;
-})
-
-(define_insn "*sse_sfence"
- [(set (match_operand:BLK 0 "" "")
- (unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "sfence"
- [(set_attr "type" "sse")
- (set_attr "length_address" "0")
- (set_attr "atom_sse_attr" "fence")
- (set_attr "memory" "unknown")])
-
(define_insn "sse2_clflush"
[(unspec_volatile [(match_operand 0 "address_operand" "p")]
UNSPECV_CLFLUSH)]
@@ -8033,43 +8109,6 @@
(set_attr "atom_sse_attr" "fence")
(set_attr "memory" "unknown")])
-(define_expand "sse2_mfence"
- [(set (match_dup 0)
- (unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))]
- "TARGET_SSE2"
-{
- operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
- MEM_VOLATILE_P (operands[0]) = 1;
-})
-
-(define_insn "*sse2_mfence"
- [(set (match_operand:BLK 0 "" "")
- (unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))]
- "TARGET_64BIT || TARGET_SSE2"
- "mfence"
- [(set_attr "type" "sse")
- (set_attr "length_address" "0")
- (set_attr "atom_sse_attr" "fence")
- (set_attr "memory" "unknown")])
-
-(define_expand "sse2_lfence"
- [(set (match_dup 0)
- (unspec:BLK [(match_dup 0)] UNSPEC_LFENCE))]
- "TARGET_SSE2"
-{
- operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
- MEM_VOLATILE_P (operands[0]) = 1;
-})
-
-(define_insn "*sse2_lfence"
- [(set (match_operand:BLK 0 "" "")
- (unspec:BLK [(match_dup 0)] UNSPEC_LFENCE))]
- "TARGET_SSE2"
- "lfence"
- [(set_attr "type" "sse")
- (set_attr "length_address" "0")
- (set_attr "atom_sse_attr" "lfence")
- (set_attr "memory" "unknown")])
(define_insn "sse3_mwait"
[(unspec_volatile [(match_operand:SI 0 "register_operand" "a")
@@ -9902,6 +9941,60 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "<MODE>")])
+(define_expand "<sse4_1>_round<ssemodesuffix>_sfix<avxsizesuffix>"
+ [(match_operand:<sseintvecmode> 0 "register_operand" "")
+ (match_operand:VF1 1 "nonimmediate_operand" "")
+ (match_operand:SI 2 "const_0_to_15_operand" "")]
+ "TARGET_ROUND"
+{
+ rtx tmp = gen_reg_rtx (<MODE>mode);
+
+ emit_insn
+ (gen_<sse4_1>_round<ssemodesuffix><avxsizesuffix> (tmp, operands[1],
+ operands[2]));
+ emit_insn
+ (gen_fix_trunc<mode><sseintvecmodelower>2 (operands[0], tmp));
+ DONE;
+})
+
+(define_expand "<sse4_1>_round<ssemodesuffix>_vec_pack_sfix<avxsizesuffix>"
+ [(match_operand:<ssepackfltmode> 0 "register_operand" "")
+ (match_operand:VF2 1 "nonimmediate_operand" "")
+ (match_operand:VF2 2 "nonimmediate_operand" "")
+ (match_operand:SI 3 "const_0_to_15_operand" "")]
+ "TARGET_ROUND"
+{
+ rtx tmp0, tmp1;
+
+ if (<MODE>mode == V2DFmode
+ && TARGET_AVX && !TARGET_PREFER_AVX128)
+ {
+ rtx tmp2 = gen_reg_rtx (V4DFmode);
+
+ tmp0 = gen_reg_rtx (V4DFmode);
+ tmp1 = force_reg (V2DFmode, operands[1]);
+
+ emit_insn (gen_avx_vec_concatv4df (tmp0, tmp1, operands[2]));
+ emit_insn (gen_avx_roundpd256 (tmp2, tmp0, operands[3]));
+ emit_insn (gen_fix_truncv4dfv4si2 (operands[0], tmp2));
+ }
+ else
+ {
+ tmp0 = gen_reg_rtx (<MODE>mode);
+ tmp1 = gen_reg_rtx (<MODE>mode);
+
+ emit_insn
+ (gen_<sse4_1>_round<ssemodesuffix><avxsizesuffix> (tmp0, operands[1],
+ operands[3]));
+ emit_insn
+ (gen_<sse4_1>_round<ssemodesuffix><avxsizesuffix> (tmp1, operands[2],
+ operands[3]));
+ emit_insn
+ (gen_vec_pack_sfix_trunc_<mode> (operands[0], tmp0, tmp1));
+ }
+ DONE;
+})
+
(define_insn "sse4_1_round<ssescalarmodesuffix>"
[(set (match_operand:VF_128 0 "register_operand" "=x,x")
(vec_merge:VF_128
@@ -9926,7 +10019,7 @@
(define_expand "round<mode>2"
[(set (match_dup 4)
(plus:VF
- (match_operand:VF 1 "nonimmediate_operand" "")
+ (match_operand:VF 1 "register_operand" "")
(match_dup 3)))
(set (match_operand:VF 0 "register_operand" "")
(unspec:VF
@@ -9957,6 +10050,54 @@
operands[5] = GEN_INT (ROUND_TRUNC);
})
+(define_expand "round<mode>2_sfix"
+ [(match_operand:<sseintvecmode> 0 "register_operand" "")
+ (match_operand:VF1 1 "register_operand" "")]
+ "TARGET_ROUND && !flag_trapping_math"
+{
+ rtx tmp = gen_reg_rtx (<MODE>mode);
+
+ emit_insn (gen_round<mode>2 (tmp, operands[1]));
+
+ emit_insn
+ (gen_fix_trunc<mode><sseintvecmodelower>2 (operands[0], tmp));
+ DONE;
+})
+
+(define_expand "round<mode>2_vec_pack_sfix"
+ [(match_operand:<ssepackfltmode> 0 "register_operand" "")
+ (match_operand:VF2 1 "register_operand" "")
+ (match_operand:VF2 2 "register_operand" "")]
+ "TARGET_ROUND && !flag_trapping_math"
+{
+ rtx tmp0, tmp1;
+
+ if (<MODE>mode == V2DFmode
+ && TARGET_AVX && !TARGET_PREFER_AVX128)
+ {
+ rtx tmp2 = gen_reg_rtx (V4DFmode);
+
+ tmp0 = gen_reg_rtx (V4DFmode);
+ tmp1 = force_reg (V2DFmode, operands[1]);
+
+ emit_insn (gen_avx_vec_concatv4df (tmp0, tmp1, operands[2]));
+ emit_insn (gen_roundv4df2 (tmp2, tmp0));
+ emit_insn (gen_fix_truncv4dfv4si2 (operands[0], tmp2));
+ }
+ else
+ {
+ tmp0 = gen_reg_rtx (<MODE>mode);
+ tmp1 = gen_reg_rtx (<MODE>mode);
+
+ emit_insn (gen_round<mode>2 (tmp0, operands[1]));
+ emit_insn (gen_round<mode>2 (tmp1, operands[2]));
+
+ emit_insn
+ (gen_vec_pack_sfix_trunc_<mode> (operands[0], tmp0, tmp1));
+ }
+ DONE;
+})
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Intel SSE4.2 string/text processing instructions
diff --git a/gcc/config/i386/sync.md b/gcc/config/i386/sync.md
index 0ff17123f27..5799b0aca50 100644
--- a/gcc/config/i386/sync.md
+++ b/gcc/config/i386/sync.md
@@ -18,26 +18,79 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
-(define_expand "mem_thread_fence"
- [(match_operand:SI 0 "const_int_operand" "")] ;; model
- ""
+(define_c_enum "unspec" [
+ UNSPEC_LFENCE
+ UNSPEC_SFENCE
+ UNSPEC_MFENCE
+ UNSPEC_MOVA ; For __atomic support
+])
+
+(define_c_enum "unspecv" [
+ UNSPECV_CMPXCHG_1
+ UNSPECV_CMPXCHG_2
+ UNSPECV_CMPXCHG_3
+ UNSPECV_CMPXCHG_4
+ UNSPECV_XCHG
+ UNSPECV_LOCK
+])
+
+(define_expand "sse2_lfence"
+ [(set (match_dup 0)
+ (unspec:BLK [(match_dup 0)] UNSPEC_LFENCE))]
+ "TARGET_SSE2"
{
- /* Unless this is a SEQ_CST fence, the i386 memory model is strong
- enough not to require barriers of any kind. */
- if (INTVAL (operands[0]) != MEMMODEL_SEQ_CST)
- DONE;
+ operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+ MEM_VOLATILE_P (operands[0]) = 1;
+})
- if (TARGET_64BIT || TARGET_SSE2)
- emit_insn (gen_sse2_mfence ());
- else
- {
- rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
- MEM_VOLATILE_P (mem) = 1;
- emit_insn (gen_mfence_nosse (mem));
- }
- DONE;
+(define_insn "*sse2_lfence"
+ [(set (match_operand:BLK 0 "" "")
+ (unspec:BLK [(match_dup 0)] UNSPEC_LFENCE))]
+ "TARGET_SSE2"
+ "lfence"
+ [(set_attr "type" "sse")
+ (set_attr "length_address" "0")
+ (set_attr "atom_sse_attr" "lfence")
+ (set_attr "memory" "unknown")])
+
+(define_expand "sse_sfence"
+ [(set (match_dup 0)
+ (unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))]
+ "TARGET_SSE || TARGET_3DNOW_A"
+{
+ operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+ MEM_VOLATILE_P (operands[0]) = 1;
})
+(define_insn "*sse_sfence"
+ [(set (match_operand:BLK 0 "" "")
+ (unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))]
+ "TARGET_SSE || TARGET_3DNOW_A"
+ "sfence"
+ [(set_attr "type" "sse")
+ (set_attr "length_address" "0")
+ (set_attr "atom_sse_attr" "fence")
+ (set_attr "memory" "unknown")])
+
+(define_expand "sse2_mfence"
+ [(set (match_dup 0)
+ (unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))]
+ "TARGET_SSE2"
+{
+ operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+ MEM_VOLATILE_P (operands[0]) = 1;
+})
+
+(define_insn "mfence_sse2"
+ [(set (match_operand:BLK 0 "" "")
+ (unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))]
+ "TARGET_64BIT || TARGET_SSE2"
+ "mfence"
+ [(set_attr "type" "sse")
+ (set_attr "length_address" "0")
+ (set_attr "atom_sse_attr" "fence")
+ (set_attr "memory" "unknown")])
+
(define_insn "mfence_nosse"
[(set (match_operand:BLK 0 "" "")
(unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))
@@ -46,7 +99,31 @@
"lock{%;} or{l}\t{$0, (%%esp)|DWORD PTR [esp], 0}"
[(set_attr "memory" "unknown")])
-;; ??? From volume 3 section 7.1.1 Guaranteed Atomic Operations,
+(define_expand "mem_thread_fence"
+ [(match_operand:SI 0 "const_int_operand" "")] ;; model
+ ""
+{
+ /* Unless this is a SEQ_CST fence, the i386 memory model is strong
+ enough not to require barriers of any kind. */
+ if (INTVAL (operands[0]) == MEMMODEL_SEQ_CST)
+ {
+ rtx (*mfence_insn)(rtx);
+ rtx mem;
+
+ if (TARGET_64BIT || TARGET_SSE2)
+ mfence_insn = gen_mfence_sse2;
+ else
+ mfence_insn = gen_mfence_nosse;
+
+ mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+ MEM_VOLATILE_P (mem) = 1;
+
+ emit_insn (mfence_insn (mem));
+ }
+ DONE;
+})
+
+;; ??? From volume 3 section 8.1.1 Guaranteed Atomic Operations,
;; Only beginning at Pentium family processors do we get any guarantee of
;; atomicity in aligned 64-bit quantities. Beginning at P6, we get a
;; guarantee for 64-bit accesses that do not cross a cacheline boundary.
@@ -204,7 +281,7 @@
(unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_MOVA))
(clobber (match_operand:DF 2 "register_operand" "=f"))]
"TARGET_80387"
- "fild\t%1\;fistp\t%0"
+ "fild%Z1\t%1\;fistp%Z0\t%0"
[(set_attr "type" "multi")
;; Worst case based on full sib+offset32 addressing modes
(set_attr "length" "14")])
diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h
index 893ed886103..c24f831601c 100644
--- a/gcc/config/ia64/ia64-protos.h
+++ b/gcc/config/ia64/ia64-protos.h
@@ -47,7 +47,8 @@ extern void ia64_expand_dot_prod_v8qi (rtx[], bool);
extern void ia64_expand_call (rtx, rtx, rtx, int);
extern void ia64_split_call (rtx, rtx, rtx, rtx, rtx, int, int);
extern void ia64_reload_gp (void);
-extern void ia64_expand_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx);
+extern void ia64_expand_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx,
+ enum memmodel);
extern HOST_WIDE_INT ia64_initial_elimination_offset (int, int);
extern void ia64_expand_prologue (void);
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index cad6d0f156c..14993676ccc 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -2266,7 +2266,7 @@ ia64_split_call (rtx retval, rtx addr, rtx retaddr, rtx scratch_r,
void
ia64_expand_atomic_op (enum rtx_code code, rtx mem, rtx val,
- rtx old_dst, rtx new_dst)
+ rtx old_dst, rtx new_dst, enum memmodel model)
{
enum machine_mode mode = GET_MODE (mem);
rtx old_reg, new_reg, cmp_reg, ar_ccv, label;
@@ -2283,12 +2283,31 @@ ia64_expand_atomic_op (enum rtx_code code, rtx mem, rtx val,
if (!old_dst)
old_dst = gen_reg_rtx (mode);
- emit_insn (gen_memory_barrier ());
+ switch (model)
+ {
+ case MEMMODEL_ACQ_REL:
+ case MEMMODEL_SEQ_CST:
+ emit_insn (gen_memory_barrier ());
+ /* FALLTHRU */
+ case MEMMODEL_RELAXED:
+ case MEMMODEL_ACQUIRE:
+ case MEMMODEL_CONSUME:
+ if (mode == SImode)
+ icode = CODE_FOR_fetchadd_acq_si;
+ else
+ icode = CODE_FOR_fetchadd_acq_di;
+ break;
+ case MEMMODEL_RELEASE:
+ if (mode == SImode)
+ icode = CODE_FOR_fetchadd_rel_si;
+ else
+ icode = CODE_FOR_fetchadd_rel_di;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
- if (mode == SImode)
- icode = CODE_FOR_fetchadd_acq_si;
- else
- icode = CODE_FOR_fetchadd_acq_di;
emit_insn (GEN_FCN (icode) (old_dst, mem, val));
if (new_dst)
@@ -2302,8 +2321,12 @@ ia64_expand_atomic_op (enum rtx_code code, rtx mem, rtx val,
}
/* Because of the volatile mem read, we get an ld.acq, which is the
- front half of the full barrier. The end half is the cmpxchg.rel. */
- gcc_assert (MEM_VOLATILE_P (mem));
+ front half of the full barrier. The end half is the cmpxchg.rel.
+ For relaxed and release memory models, we don't need this. But we
+ also don't bother trying to prevent it either. */
+ gcc_assert (model == MEMMODEL_RELAXED
+ || model == MEMMODEL_RELEASE
+ || MEM_VOLATILE_P (mem));
old_reg = gen_reg_rtx (DImode);
cmp_reg = gen_reg_rtx (DImode);
@@ -2342,12 +2365,36 @@ ia64_expand_atomic_op (enum rtx_code code, rtx mem, rtx val,
if (new_dst)
emit_move_insn (new_dst, new_reg);
- switch (mode)
+ switch (model)
{
- case QImode: icode = CODE_FOR_cmpxchg_rel_qi; break;
- case HImode: icode = CODE_FOR_cmpxchg_rel_hi; break;
- case SImode: icode = CODE_FOR_cmpxchg_rel_si; break;
- case DImode: icode = CODE_FOR_cmpxchg_rel_di; break;
+ case MEMMODEL_RELAXED:
+ case MEMMODEL_ACQUIRE:
+ case MEMMODEL_CONSUME:
+ switch (mode)
+ {
+ case QImode: icode = CODE_FOR_cmpxchg_acq_qi; break;
+ case HImode: icode = CODE_FOR_cmpxchg_acq_hi; break;
+ case SImode: icode = CODE_FOR_cmpxchg_acq_si; break;
+ case DImode: icode = CODE_FOR_cmpxchg_acq_di; break;
+ default:
+ gcc_unreachable ();
+ }
+ break;
+
+ case MEMMODEL_RELEASE:
+ case MEMMODEL_ACQ_REL:
+ case MEMMODEL_SEQ_CST:
+ switch (mode)
+ {
+ case QImode: icode = CODE_FOR_cmpxchg_rel_qi; break;
+ case HImode: icode = CODE_FOR_cmpxchg_rel_hi; break;
+ case SImode: icode = CODE_FOR_cmpxchg_rel_si; break;
+ case DImode: icode = CODE_FOR_cmpxchg_rel_di; break;
+ default:
+ gcc_unreachable ();
+ }
+ break;
+
default:
gcc_unreachable ();
}
@@ -6342,6 +6389,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
case UNSPEC_PIC_CALL:
case UNSPEC_MF:
case UNSPEC_FETCHADD_ACQ:
+ case UNSPEC_FETCHADD_REL:
case UNSPEC_BSP_VALUE:
case UNSPEC_FLUSHRS:
case UNSPEC_BUNDLE_SELECTOR:
@@ -6385,6 +6433,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
break;
case UNSPEC_CMPXCHG_ACQ:
+ case UNSPEC_CMPXCHG_REL:
need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 1), flags, pred);
need_barrier |= rtx_needs_barrier (XVECEXP (x, 0, 2), flags, pred);
break;
diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md
index 46eebc25ad8..129cec80fcf 100644
--- a/gcc/config/ia64/ia64.md
+++ b/gcc/config/ia64/ia64.md
@@ -48,61 +48,63 @@
;; ??? Need a better way to describe alternate fp status registers.
-(define_constants
+(define_c_enum "unspec"
[; Relocations
- (UNSPEC_LTOFF_DTPMOD 0)
- (UNSPEC_LTOFF_DTPREL 1)
- (UNSPEC_DTPREL 2)
- (UNSPEC_LTOFF_TPREL 3)
- (UNSPEC_TPREL 4)
- (UNSPEC_DTPMOD 5)
-
- (UNSPEC_LD_BASE 9)
- (UNSPEC_GR_SPILL 10)
- (UNSPEC_GR_RESTORE 11)
- (UNSPEC_FR_SPILL 12)
- (UNSPEC_FR_RESTORE 13)
- (UNSPEC_FR_RECIP_APPROX 14)
- (UNSPEC_PRED_REL_MUTEX 15)
- (UNSPEC_GETF_EXP 16)
- (UNSPEC_PIC_CALL 17)
- (UNSPEC_MF 18)
- (UNSPEC_CMPXCHG_ACQ 19)
- (UNSPEC_FETCHADD_ACQ 20)
- (UNSPEC_BSP_VALUE 21)
- (UNSPEC_FLUSHRS 22)
- (UNSPEC_BUNDLE_SELECTOR 23)
- (UNSPEC_ADDP4 24)
- (UNSPEC_PROLOGUE_USE 25)
- (UNSPEC_RET_ADDR 26)
- (UNSPEC_SETF_EXP 27)
- (UNSPEC_FR_SQRT_RECIP_APPROX 28)
- (UNSPEC_SHRP 29)
- (UNSPEC_COPYSIGN 30)
- (UNSPEC_VECT_EXTR 31)
- (UNSPEC_LDA 40)
- (UNSPEC_LDS 41)
- (UNSPEC_LDS_A 42)
- (UNSPEC_LDSA 43)
- (UNSPEC_LDCCLR 44)
- (UNSPEC_LDCNC 45)
- (UNSPEC_CHKACLR 46)
- (UNSPEC_CHKANC 47)
- (UNSPEC_CHKS 48)
- (UNSPEC_FR_RECIP_APPROX_RES 49)
- (UNSPEC_FR_SQRT_RECIP_APPROX_RES 50)
+ UNSPEC_LTOFF_DTPMOD
+ UNSPEC_LTOFF_DTPREL
+ UNSPEC_DTPREL
+ UNSPEC_LTOFF_TPREL
+ UNSPEC_TPREL
+ UNSPEC_DTPMOD
+
+ UNSPEC_LD_BASE
+ UNSPEC_GR_SPILL
+ UNSPEC_GR_RESTORE
+ UNSPEC_FR_SPILL
+ UNSPEC_FR_RESTORE
+ UNSPEC_FR_RECIP_APPROX
+ UNSPEC_PRED_REL_MUTEX
+ UNSPEC_GETF_EXP
+ UNSPEC_PIC_CALL
+ UNSPEC_MF
+ UNSPEC_CMPXCHG_ACQ
+ UNSPEC_CMPXCHG_REL
+ UNSPEC_FETCHADD_ACQ
+ UNSPEC_FETCHADD_REL
+ UNSPEC_BSP_VALUE
+ UNSPEC_FLUSHRS
+ UNSPEC_BUNDLE_SELECTOR
+ UNSPEC_ADDP4
+ UNSPEC_PROLOGUE_USE
+ UNSPEC_RET_ADDR
+ UNSPEC_SETF_EXP
+ UNSPEC_FR_SQRT_RECIP_APPROX
+ UNSPEC_SHRP
+ UNSPEC_COPYSIGN
+ UNSPEC_VECT_EXTR
+ UNSPEC_LDA
+ UNSPEC_LDS
+ UNSPEC_LDS_A
+ UNSPEC_LDSA
+ UNSPEC_LDCCLR
+ UNSPEC_LDCNC
+ UNSPEC_CHKACLR
+ UNSPEC_CHKANC
+ UNSPEC_CHKS
+ UNSPEC_FR_RECIP_APPROX_RES
+ UNSPEC_FR_SQRT_RECIP_APPROX_RES
])
-(define_constants
- [(UNSPECV_ALLOC 0)
- (UNSPECV_BLOCKAGE 1)
- (UNSPECV_INSN_GROUP_BARRIER 2)
- (UNSPECV_BREAK 3)
- (UNSPECV_SET_BSP 4)
- (UNSPECV_PSAC_ALL 5) ; pred.safe_across_calls
- (UNSPECV_PSAC_NORMAL 6)
- (UNSPECV_SETJMP_RECEIVER 7)
- (UNSPECV_GOTO_RECEIVER 8)
+(define_c_enum "unspecv" [
+ UNSPECV_ALLOC
+ UNSPECV_BLOCKAGE
+ UNSPECV_INSN_GROUP_BARRIER
+ UNSPECV_BREAK
+ UNSPECV_SET_BSP
+ UNSPECV_PSAC_ALL ; pred.safe_across_calls
+ UNSPECV_PSAC_NORMAL
+ UNSPECV_SETJMP_RECEIVER
+ UNSPECV_GOTO_RECEIVER
])
(include "predicates.md")
diff --git a/gcc/config/ia64/sync.md b/gcc/config/ia64/sync.md
index 06ca8f09b40..152e4f5a8a0 100644
--- a/gcc/config/ia64/sync.md
+++ b/gcc/config/ia64/sync.md
@@ -18,6 +18,9 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
+;; Conversion to C++11 memory model based on
+;; http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
+
(define_mode_iterator IMODE [QI HI SI DI])
(define_mode_iterator I124MODE [QI HI SI])
(define_mode_iterator I48MODE [SI DI])
@@ -27,6 +30,15 @@
(define_code_attr fetchop_name
[(plus "add") (minus "sub") (ior "ior") (xor "xor") (and "and")])
+(define_expand "mem_thread_fence"
+ [(match_operand:SI 0 "const_int_operand" "")] ;; model
+ ""
+{
+ if (INTVAL (operands[0]) == MEMMODEL_SEQ_CST)
+ emit_insn (gen_memory_barrier ());
+ DONE;
+})
+
(define_expand "memory_barrier"
[(set (match_dup 0)
(unspec:BLK [(match_dup 0)] UNSPEC_MF))]
@@ -43,107 +55,94 @@
"mf"
[(set_attr "itanium_class" "syst_m")])
-(define_insn "fetchadd_acq_<mode>"
- [(set (match_operand:I48MODE 0 "gr_register_operand" "=r")
- (match_operand:I48MODE 1 "not_postinc_memory_operand" "+S"))
- (set (match_dup 1)
- (unspec:I48MODE [(match_dup 1)
- (match_operand:I48MODE 2 "fetchadd_operand" "n")]
- UNSPEC_FETCHADD_ACQ))]
- ""
- "fetchadd<modesuffix>.acq %0 = %1, %2"
- [(set_attr "itanium_class" "sem")])
-
-(define_expand "sync_<fetchop_name><mode>"
- [(set (match_operand:IMODE 0 "memory_operand" "")
- (FETCHOP:IMODE (match_dup 0)
- (match_operand:IMODE 1 "general_operand" "")))]
- ""
-{
- ia64_expand_atomic_op (<CODE>, operands[0], operands[1], NULL, NULL);
- DONE;
-})
-
-(define_expand "sync_nand<mode>"
- [(set (match_operand:IMODE 0 "memory_operand" "")
- (not:IMODE
- (and:IMODE (match_dup 0)
- (match_operand:IMODE 1 "general_operand" ""))))]
+(define_expand "atomic_load<mode>"
+ [(match_operand:IMODE 0 "gr_register_operand" "") ;; output
+ (match_operand:IMODE 1 "memory_operand" "") ;; memory
+ (match_operand:SI 2 "const_int_operand" "")] ;; model
""
{
- ia64_expand_atomic_op (NOT, operands[0], operands[1], NULL, NULL);
- DONE;
-})
+ enum memmodel model = (enum memmodel) INTVAL (operands[2]);
-(define_expand "sync_old_<fetchop_name><mode>"
- [(set (match_operand:IMODE 0 "gr_register_operand" "")
- (FETCHOP:IMODE
- (match_operand:IMODE 1 "memory_operand" "")
- (match_operand:IMODE 2 "general_operand" "")))]
- ""
-{
- ia64_expand_atomic_op (<CODE>, operands[1], operands[2], operands[0], NULL);
+ /* Unless the memory model is relaxed, we want to emit ld.acq, which
+ will happen automatically for volatile memories. */
+ gcc_assert (model == MEMMODEL_RELAXED || MEM_VOLATILE_P (operands[1]));
+ emit_move_insn (operands[0], operands[1]);
DONE;
})
-(define_expand "sync_old_nand<mode>"
- [(set (match_operand:IMODE 0 "gr_register_operand" "")
- (not:IMODE
- (and:IMODE (match_operand:IMODE 1 "memory_operand" "")
- (match_operand:IMODE 2 "general_operand" ""))))]
+(define_expand "atomic_store<mode>"
+ [(match_operand:IMODE 0 "memory_operand" "") ;; memory
+ (match_operand:IMODE 1 "gr_reg_or_0_operand" "") ;; input
+ (match_operand:SI 2 "const_int_operand" "")] ;; model
""
{
- ia64_expand_atomic_op (NOT, operands[1], operands[2], operands[0], NULL);
- DONE;
-})
+ enum memmodel model = (enum memmodel) INTVAL (operands[2]);
-(define_expand "sync_new_<fetchop_name><mode>"
- [(set (match_operand:IMODE 0 "gr_register_operand" "")
- (FETCHOP:IMODE
- (match_operand:IMODE 1 "memory_operand" "")
- (match_operand:IMODE 2 "general_operand" "")))]
- ""
-{
- ia64_expand_atomic_op (<CODE>, operands[1], operands[2], NULL, operands[0]);
- DONE;
-})
+ /* Unless the memory model is relaxed, we want to emit st.rel, which
+ will happen automatically for volatile memories. */
+ gcc_assert (model == MEMMODEL_RELAXED || MEM_VOLATILE_P (operands[0]));
+ emit_move_insn (operands[0], operands[1]);
-(define_expand "sync_new_nand<mode>"
- [(set (match_operand:IMODE 0 "gr_register_operand" "")
- (not:IMODE
- (and:IMODE (match_operand:IMODE 1 "memory_operand" "")
- (match_operand:IMODE 2 "general_operand" ""))))]
- ""
-{
- ia64_expand_atomic_op (NOT, operands[1], operands[2], NULL, operands[0]);
+ /* Sequentially consistent stores need a subsequent MF. See
+ http://www.decadent.org.uk/pipermail/cpp-threads/2008-December/001952.html
+ for a discussion of why a MF is needed here, but not for atomic_load. */
+ if (model == MEMMODEL_SEQ_CST)
+ emit_insn (gen_memory_barrier ());
DONE;
})
-(define_expand "sync_compare_and_swap<mode>"
- [(match_operand:IMODE 0 "gr_register_operand" "")
- (match_operand:IMODE 1 "memory_operand" "")
- (match_operand:IMODE 2 "gr_register_operand" "")
- (match_operand:IMODE 3 "gr_register_operand" "")]
+(define_expand "atomic_compare_and_swap<mode>"
+ [(match_operand:DI 0 "gr_register_operand" "") ;; bool out
+ (match_operand:IMODE 1 "gr_register_operand" "") ;; val out
+ (match_operand:IMODE 2 "not_postinc_memory_operand" "") ;; memory
+ (match_operand:IMODE 3 "gr_register_operand" "") ;; expected
+ (match_operand:IMODE 4 "gr_reg_or_0_operand" "") ;; desired
+ (match_operand:SI 5 "const_int_operand" "") ;; is_weak
+ (match_operand:SI 6 "const_int_operand" "") ;; succ model
+ (match_operand:SI 7 "const_int_operand" "")] ;; fail model
""
{
+ enum memmodel model = (enum memmodel) INTVAL (operands[6]);
rtx ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
- rtx dst;
+ rtx dval, eval;
+
+ eval = gen_reg_rtx (DImode);
+ convert_move (eval, operands[3], 1);
+ emit_move_insn (ccv, eval);
- convert_move (ccv, operands[2], 1);
+ if (<MODE>mode == DImode)
+ dval = operands[1];
+ else
+ dval = gen_reg_rtx (DImode);
- dst = operands[0];
- if (GET_MODE (dst) != DImode)
- dst = gen_reg_rtx (DImode);
+ switch (model)
+ {
+ case MEMMODEL_RELAXED:
+ case MEMMODEL_ACQUIRE:
+ case MEMMODEL_CONSUME:
+ emit_insn (gen_cmpxchg_acq_<mode> (dval, operands[2], ccv, operands[4]));
+ break;
+ case MEMMODEL_RELEASE:
+ emit_insn (gen_cmpxchg_rel_<mode> (dval, operands[2], ccv, operands[4]));
+ break;
+ case MEMMODEL_ACQ_REL:
+ case MEMMODEL_SEQ_CST:
+ emit_insn (gen_cmpxchg_rel_<mode> (dval, operands[2], ccv, operands[4]));
+ emit_insn (gen_memory_barrier ());
+ break;
+ default:
+ gcc_unreachable ();
+ }
- emit_insn (gen_cmpxchg_rel_<mode> (dst, operands[1], ccv, operands[3]));
- emit_insn (gen_memory_barrier ());
+ if (<MODE>mode != DImode)
+ emit_move_insn (operands[1], gen_lowpart (<MODE>mode, dval));
- if (dst != operands[0])
- emit_move_insn (operands[0], gen_lowpart (<MODE>mode, dst));
+ emit_insn (gen_cstoredi4 (operands[0], gen_rtx_EQ (DImode, dval, eval),
+ dval, eval));
DONE;
})
-(define_insn "cmpxchg_rel_<mode>"
+(define_insn "cmpxchg_acq_<mode>"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
(zero_extend:DI
(match_operand:I124MODE 1 "not_postinc_memory_operand" "+S")))
@@ -154,10 +153,24 @@
(match_operand:I124MODE 3 "gr_reg_or_0_operand" "rO")]
UNSPEC_CMPXCHG_ACQ))]
""
+ "cmpxchg<modesuffix>.acq %0 = %1, %r3, %2"
+ [(set_attr "itanium_class" "sem")])
+
+(define_insn "cmpxchg_rel_<mode>"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (zero_extend:DI
+ (match_operand:I124MODE 1 "not_postinc_memory_operand" "+S")))
+ (set (match_dup 1)
+ (unspec:I124MODE
+ [(match_dup 1)
+ (match_operand:DI 2 "ar_ccv_reg_operand" "")
+ (match_operand:I124MODE 3 "gr_reg_or_0_operand" "rO")]
+ UNSPEC_CMPXCHG_REL))]
+ ""
"cmpxchg<modesuffix>.rel %0 = %1, %r3, %2"
[(set_attr "itanium_class" "sem")])
-(define_insn "cmpxchg_rel_di"
+(define_insn "cmpxchg_acq_di"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
(match_operand:DI 1 "not_postinc_memory_operand" "+S"))
(set (match_dup 1)
@@ -166,10 +179,50 @@
(match_operand:DI 3 "gr_reg_or_0_operand" "rO")]
UNSPEC_CMPXCHG_ACQ))]
""
+ "cmpxchg8.acq %0 = %1, %r3, %2"
+ [(set_attr "itanium_class" "sem")])
+
+(define_insn "cmpxchg_rel_di"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (match_operand:DI 1 "not_postinc_memory_operand" "+S"))
+ (set (match_dup 1)
+ (unspec:DI [(match_dup 1)
+ (match_operand:DI 2 "ar_ccv_reg_operand" "")
+ (match_operand:DI 3 "gr_reg_or_0_operand" "rO")]
+ UNSPEC_CMPXCHG_REL))]
+ ""
"cmpxchg8.rel %0 = %1, %r3, %2"
[(set_attr "itanium_class" "sem")])
-(define_insn "sync_lock_test_and_set<mode>"
+(define_expand "atomic_exchange<mode>"
+ [(match_operand:IMODE 0 "gr_register_operand" "") ;; output
+ (match_operand:IMODE 1 "not_postinc_memory_operand" "") ;; memory
+ (match_operand:IMODE 2 "gr_reg_or_0_operand" "") ;; input
+ (match_operand:SI 3 "const_int_operand" "")] ;; succ model
+ ""
+{
+ enum memmodel model = (enum memmodel) INTVAL (operands[3]);
+
+ switch (model)
+ {
+ case MEMMODEL_RELAXED:
+ case MEMMODEL_ACQUIRE:
+ case MEMMODEL_CONSUME:
+ break;
+ case MEMMODEL_RELEASE:
+ case MEMMODEL_ACQ_REL:
+ case MEMMODEL_SEQ_CST:
+ emit_insn (gen_memory_barrier ());
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ emit_insn (gen_xchg_acq_<mode> (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+;; Note that XCHG is always memory model acquire.
+(define_insn "xchg_acq_<mode>"
[(set (match_operand:IMODE 0 "gr_register_operand" "=r")
(match_operand:IMODE 1 "not_postinc_memory_operand" "+S"))
(set (match_dup 1)
@@ -178,10 +231,101 @@
"xchg<modesuffix> %0 = %1, %r2"
[(set_attr "itanium_class" "sem")])
-(define_expand "sync_lock_release<mode>"
+(define_expand "atomic_<fetchop_name><mode>"
[(set (match_operand:IMODE 0 "memory_operand" "")
- (match_operand:IMODE 1 "gr_reg_or_0_operand" ""))]
+ (FETCHOP:IMODE (match_dup 0)
+ (match_operand:IMODE 1 "nonmemory_operand" "")))
+ (use (match_operand:SI 2 "const_int_operand" ""))]
+ ""
+{
+ ia64_expand_atomic_op (<CODE>, operands[0], operands[1], NULL, NULL,
+ (enum memmodel) INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "atomic_nand<mode>"
+ [(set (match_operand:IMODE 0 "memory_operand" "")
+ (not:IMODE
+ (and:IMODE (match_dup 0)
+ (match_operand:IMODE 1 "nonmemory_operand" ""))))
+ (use (match_operand:SI 2 "const_int_operand" ""))]
+ ""
+{
+ ia64_expand_atomic_op (NOT, operands[0], operands[1], NULL, NULL,
+ (enum memmodel) INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "atomic_fetch_<fetchop_name><mode>"
+ [(set (match_operand:IMODE 0 "gr_register_operand" "")
+ (FETCHOP:IMODE
+ (match_operand:IMODE 1 "memory_operand" "")
+ (match_operand:IMODE 2 "nonmemory_operand" "")))
+ (use (match_operand:SI 3 "const_int_operand" ""))]
""
{
- gcc_assert (MEM_VOLATILE_P (operands[0]));
+ ia64_expand_atomic_op (<CODE>, operands[1], operands[2], operands[0], NULL,
+ (enum memmodel) INTVAL (operands[3]));
+ DONE;
+})
+
+(define_expand "atomic_fetch_nand<mode>"
+ [(set (match_operand:IMODE 0 "gr_register_operand" "")
+ (not:IMODE
+ (and:IMODE (match_operand:IMODE 1 "memory_operand" "")
+ (match_operand:IMODE 2 "nonmemory_operand" ""))))
+ (use (match_operand:SI 3 "const_int_operand" ""))]
+ ""
+{
+ ia64_expand_atomic_op (NOT, operands[1], operands[2], operands[0], NULL,
+ (enum memmodel) INTVAL (operands[3]));
+ DONE;
})
+
+(define_expand "atomic_<fetchop_name>_fetch<mode>"
+ [(set (match_operand:IMODE 0 "gr_register_operand" "")
+ (FETCHOP:IMODE
+ (match_operand:IMODE 1 "memory_operand" "")
+ (match_operand:IMODE 2 "nonmemory_operand" "")))
+ (use (match_operand:SI 3 "const_int_operand" ""))]
+ ""
+{
+ ia64_expand_atomic_op (<CODE>, operands[1], operands[2], NULL, operands[0],
+ (enum memmodel) INTVAL (operands[3]));
+ DONE;
+})
+
+(define_expand "atomic_nand_fetch<mode>"
+ [(set (match_operand:IMODE 0 "gr_register_operand" "")
+ (not:IMODE
+ (and:IMODE (match_operand:IMODE 1 "memory_operand" "")
+ (match_operand:IMODE 2 "nonmemory_operand" ""))))
+ (use (match_operand:SI 3 "const_int_operand" ""))]
+ ""
+{
+ ia64_expand_atomic_op (NOT, operands[1], operands[2], NULL, operands[0],
+ (enum memmodel) INTVAL (operands[3]));
+ DONE;
+})
+
+(define_insn "fetchadd_acq_<mode>"
+ [(set (match_operand:I48MODE 0 "gr_register_operand" "=r")
+ (match_operand:I48MODE 1 "not_postinc_memory_operand" "+S"))
+ (set (match_dup 1)
+ (unspec:I48MODE [(match_dup 1)
+ (match_operand:I48MODE 2 "fetchadd_operand" "n")]
+ UNSPEC_FETCHADD_ACQ))]
+ ""
+ "fetchadd<modesuffix>.acq %0 = %1, %2"
+ [(set_attr "itanium_class" "sem")])
+
+(define_insn "fetchadd_rel_<mode>"
+ [(set (match_operand:I48MODE 0 "gr_register_operand" "=r")
+ (match_operand:I48MODE 1 "not_postinc_memory_operand" "+S"))
+ (set (match_dup 1)
+ (unspec:I48MODE [(match_dup 1)
+ (match_operand:I48MODE 2 "fetchadd_operand" "n")]
+ UNSPEC_FETCHADD_REL))]
+ ""
+ "fetchadd<modesuffix>.rel %0 = %1, %2"
+ [(set_attr "itanium_class" "sem")])
diff --git a/gcc/config/m68k/linux.h b/gcc/config/m68k/linux.h
index 70738d221bf..325faf73a75 100644
--- a/gcc/config/m68k/linux.h
+++ b/gcc/config/m68k/linux.h
@@ -235,3 +235,7 @@ along with GCC; see the file COPYING3. If not see
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE BITS_PER_WORD
+
+/* Install the __sync libcalls. */
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS m68k_init_sync_libfuncs
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 51a04ed9c15..61267a80497 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see
#include "insn-codes.h"
#include "ggc.h"
#include "opts.h"
+#include "optabs.h"
enum reg_class regno_reg_class[] =
{
@@ -164,6 +165,7 @@ static rtx m68k_function_arg (cumulative_args_t, enum machine_mode,
const_tree, bool);
static bool m68k_cannot_force_const_mem (enum machine_mode mode, rtx x);
static bool m68k_output_addr_const_extra (FILE *, rtx);
+static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
/* Initialize the GCC target structure. */
@@ -6524,4 +6526,10 @@ m68k_conditional_register_usage (void)
fixed_regs[PIC_REG] = call_used_regs[PIC_REG] = 1;
}
+static void
+m68k_init_sync_libfuncs (void)
+{
+ init_sync_libfuncs (UNITS_PER_WORD);
+}
+
#include "gt-m68k.h"
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index 672ef0db6c0..e4b4b59afc2 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -124,6 +124,10 @@
(define_constants
[(UNSPECV_BLOCKAGE 0)
+ (UNSPECV_CAS_1 1)
+ (UNSPECV_CAS_2 2)
+ (UNSPECV_TAS_1 3)
+ (UNSPECV_TAS_2 4)
])
;; Registers by name.
@@ -255,6 +259,10 @@
(const_int 0)]
(const_int 1)))
+;; Mode macros for integer operations.
+(define_mode_iterator I [QI HI SI])
+(define_mode_attr sz [(QI "%.b") (HI "%.w") (SI "%.l")])
+
;; Mode macros for floating point operations.
;; Valid floating point modes
(define_mode_iterator FP [SF DF (XF "TARGET_68881")])
@@ -7806,3 +7814,4 @@
[(set_attr "type" "ib")])
(include "cf.md")
+(include "sync.md")
diff --git a/gcc/config/m68k/sync.md b/gcc/config/m68k/sync.md
new file mode 100644
index 00000000000..9a5bcda4c04
--- /dev/null
+++ b/gcc/config/m68k/sync.md
@@ -0,0 +1,80 @@
+;; GCC machine description for m68k synchronization instructions.
+;; 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/>.
+
+
+(define_expand "atomic_compare_and_swap<mode>"
+ [(match_operand:QI 0 "register_operand" "") ;; bool success output
+ (match_operand:I 1 "register_operand" "") ;; oldval output
+ (match_operand:I 2 "memory_operand" "") ;; memory
+ (match_operand:I 3 "register_operand" "") ;; expected input
+ (match_operand:I 4 "register_operand" "") ;; newval input
+ (match_operand:SI 5 "const_int_operand" "") ;; is_weak
+ (match_operand:SI 6 "const_int_operand" "") ;; success model
+ (match_operand:SI 7 "const_int_operand" "")] ;; failure model
+ "TARGET_68020 || TARGET_68040"
+{
+ emit_insn (gen_atomic_compare_and_swap<mode>_1
+ (operands[0], operands[1], operands[2],
+ operands[3], operands[4]));
+ emit_insn (gen_negqi2 (operands[0], operands[0]));
+ DONE;
+})
+
+(define_insn "atomic_compare_and_swap<mode>_1"
+ [(set (match_operand:I 1 "register_operand" "=d")
+ (unspec_volatile:I
+ [(match_operand:I 2 "memory_operand" "+m")
+ (match_operand:I 3 "register_operand" "0")
+ (match_operand:I 4 "register_operand" "d")]
+ UNSPECV_CAS_1))
+ (set (match_dup 2)
+ (unspec_volatile:I
+ [(match_dup 2) (match_dup 3) (match_dup 4)]
+ UNSPECV_CAS_2))
+ (set (match_operand:QI 0 "register_operand" "=d")
+ (unspec_volatile:QI
+ [(match_dup 2) (match_dup 3) (match_dup 4)]
+ UNSPECV_CAS_2))]
+ "TARGET_68020 || TARGET_68040"
+ ;; Elide the seq if operands[0] is dead.
+ "cas<sz> %1,%4,%2\;seq %0")
+
+(define_expand "sync_test_and_setqi"
+ [(match_operand:QI 0 "register_operand" "")
+ (match_operand:QI 1 "memory_operand" "")
+ (match_operand:QI 2 "general_operand" "")]
+ "!(TARGET_68020 || TARGET_68040)"
+{
+ if (operands[2] != const1_rtx)
+ FAIL;
+ emit_insn (gen_sync_test_and_setqi_1 (operands[0], operands[1]));
+ emit_insn (gen_negqi2 (operands[0], operands[0]));
+ DONE;
+})
+
+(define_insn "sync_test_and_setqi_1"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (unspec_volatile:QI
+ [(match_operand:QI 1 "memory_operand" "+m")]
+ UNSPECV_TAS_1))
+ (set (match_dup 1)
+ (unspec_volatile:QI [(match_dup 1)] UNSPECV_TAS_2))]
+ "!(TARGET_68020 || TARGET_68040)"
+ "tas %1\;sne %0")
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h
index b28b0b39165..dbabdffaef0 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -191,6 +191,9 @@ extern int mips_split_const_insns (rtx);
extern int mips_load_store_insns (rtx, rtx);
extern int mips_idiv_insns (void);
extern rtx mips_emit_move (rtx, rtx);
+#ifdef RTX_CODE
+extern void mips_emit_binary (enum rtx_code, rtx, rtx, rtx);
+#endif
extern rtx mips_pic_base_register (rtx);
extern rtx mips_got_load (rtx, rtx, enum mips_symbol_type);
extern bool mips_split_symbol (rtx, rtx, enum machine_mode, rtx *);
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index ff72e28a35c..d3fd7097f57 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -2163,7 +2163,7 @@ static bool
mips16_unextended_reference_p (enum machine_mode mode, rtx base,
unsigned HOST_WIDE_INT offset)
{
- if (offset % GET_MODE_SIZE (mode) == 0)
+ if (mode != BLKmode && offset % GET_MODE_SIZE (mode) == 0)
{
if (GET_MODE_SIZE (mode) == 4 && base == stack_pointer_rtx)
return offset < 256U * GET_MODE_SIZE (mode);
@@ -2398,7 +2398,7 @@ mips_force_unary (enum machine_mode mode, enum rtx_code code, rtx op0)
/* Emit an instruction of the form (set TARGET (CODE OP0 OP1)). */
-static void
+void
mips_emit_binary (enum rtx_code code, rtx target, rtx op0, rtx op1)
{
emit_insn (gen_rtx_SET (VOIDmode, target,
@@ -3777,6 +3777,16 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
return false;
case ZERO_EXTEND:
+ if (outer_code == SET
+ && ISA_HAS_BADDU
+ && (GET_CODE (XEXP (x, 0)) == TRUNCATE
+ || GET_CODE (XEXP (x, 0)) == SUBREG)
+ && GET_MODE (XEXP (x, 0)) == QImode
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS)
+ {
+ *total = set_src_cost (XEXP (XEXP (x, 0), 0), speed);
+ return true;
+ }
*total = mips_zero_extend_cost (mode, XEXP (x, 0));
return false;
@@ -11218,9 +11228,13 @@ mips_init_libfuncs (void)
}
/* The MIPS16 ISA does not have an encoding for "sync", so we rely
- on an external non-MIPS16 routine to implement __sync_synchronize. */
+ on an external non-MIPS16 routine to implement __sync_synchronize.
+ Similarly for the rest of the ll/sc libfuncs. */
if (TARGET_MIPS16)
- synchronize_libfunc = init_one_libfunc ("__sync_synchronize");
+ {
+ synchronize_libfunc = init_one_libfunc ("__sync_synchronize");
+ init_sync_libfuncs (UNITS_PER_WORD);
+ }
}
/* Build up a multi-insn sequence that loads label TARGET into $AT. */
@@ -15246,6 +15260,11 @@ mips_set_mips16_mode (int mips16_p)
/* MIPS16 has no BAL instruction. */
target_flags &= ~MASK_RELAX_PIC_CALLS;
+ /* The R4000 errata don't apply to any known MIPS16 cores.
+ It's simpler to make the R4000 fixes and MIPS16 mode
+ mutually exclusive. */
+ target_flags &= ~MASK_FIX_R4000;
+
if (flag_pic && !TARGET_OLDABI)
sorry ("MIPS16 PIC for ABIs other than o32 and o64");
@@ -15831,38 +15850,33 @@ mips_conditional_register_usage (void)
global_regs[CCDSP_PO_REGNUM] = 1;
global_regs[CCDSP_SC_REGNUM] = 1;
}
- else
- {
- int regno;
+ else
+ AND_COMPL_HARD_REG_SET (accessible_reg_set,
+ reg_class_contents[(int) DSP_ACC_REGS]);
- for (regno = DSP_ACC_REG_FIRST; regno <= DSP_ACC_REG_LAST; regno++)
- fixed_regs[regno] = call_used_regs[regno] = 1;
- }
if (!TARGET_HARD_FLOAT)
{
- int regno;
-
- for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
- fixed_regs[regno] = call_used_regs[regno] = 1;
- for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++)
- fixed_regs[regno] = call_used_regs[regno] = 1;
+ AND_COMPL_HARD_REG_SET (accessible_reg_set,
+ reg_class_contents[(int) FP_REGS]);
+ AND_COMPL_HARD_REG_SET (accessible_reg_set,
+ reg_class_contents[(int) ST_REGS]);
}
- else if (! ISA_HAS_8CC)
+ else if (!ISA_HAS_8CC)
{
- int regno;
-
/* We only have a single condition-code register. We implement
this by fixing all the condition-code registers and generating
RTL that refers directly to ST_REG_FIRST. */
- for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++)
- fixed_regs[regno] = call_used_regs[regno] = 1;
+ AND_COMPL_HARD_REG_SET (accessible_reg_set,
+ reg_class_contents[(int) ST_REGS]);
+ SET_HARD_REG_BIT (accessible_reg_set, FPSW_REGNUM);
+ fixed_regs[FPSW_REGNUM] = call_used_regs[FPSW_REGNUM] = 1;
}
- /* In MIPS16 mode, we permit the $t temporary registers to be used
- for reload. We prohibit the unused $s registers, since they
- are call-saved, and saving them via a MIPS16 register would
- probably waste more time than just reloading the value. */
if (TARGET_MIPS16)
{
+ /* In MIPS16 mode, we permit the $t temporary registers to be used
+ for reload. We prohibit the unused $s registers, since they
+ are call-saved, and saving them via a MIPS16 register would
+ probably waste more time than just reloading the value. */
fixed_regs[18] = call_used_regs[18] = 1;
fixed_regs[19] = call_used_regs[19] = 1;
fixed_regs[20] = call_used_regs[20] = 1;
@@ -15872,6 +15886,12 @@ mips_conditional_register_usage (void)
fixed_regs[26] = call_used_regs[26] = 1;
fixed_regs[27] = call_used_regs[27] = 1;
fixed_regs[30] = call_used_regs[30] = 1;
+
+ /* Do not allow HI and LO to be treated as register operands.
+ There are no MTHI or MTLO instructions (or any real need
+ for them) and one-way registers cannot easily be reloaded. */
+ AND_COMPL_HARD_REG_SET (operand_reg_set,
+ reg_class_contents[(int) MD_REGS]);
}
/* $f20-$f23 are call-clobbered for n64. */
if (mips_abi == ABI_64)
@@ -16057,12 +16077,20 @@ mips_mulsidi3_gen_fn (enum rtx_code ext_code)
case we still expand mulsidi3 for DMUL. */
if (ISA_HAS_DMUL3)
return signed_p ? gen_mulsidi3_64bit_dmul : NULL;
+ if (TARGET_MIPS16)
+ return (signed_p
+ ? gen_mulsidi3_64bit_mips16
+ : gen_umulsidi3_64bit_mips16);
if (TARGET_FIX_R4000)
return NULL;
return signed_p ? gen_mulsidi3_64bit : gen_umulsidi3_64bit;
}
else
{
+ if (TARGET_MIPS16)
+ return (signed_p
+ ? gen_mulsidi3_32bit_mips16
+ : gen_umulsidi3_32bit_mips16);
if (TARGET_FIX_R4000 && !ISA_HAS_DSP)
return signed_p ? gen_mulsidi3_32bit_r4000 : gen_umulsidi3_32bit_r4000;
return signed_p ? gen_mulsidi3_32bit : gen_umulsidi3_32bit;
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index c2211a3c170..55b7fffb665 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -1331,11 +1331,19 @@
(match_operand:GPR 2 "register_operand")))]
""
{
+ rtx lo;
+
if (TARGET_LOONGSON_2EF || TARGET_LOONGSON_3A)
emit_insn (gen_mul<mode>3_mul3_loongson (operands[0], operands[1],
operands[2]));
else if (ISA_HAS_<D>MUL3)
emit_insn (gen_mul<mode>3_mul3 (operands[0], operands[1], operands[2]));
+ else if (TARGET_MIPS16)
+ {
+ lo = gen_rtx_REG (<MODE>mode, LO_REGNUM);
+ emit_insn (gen_mul<mode>3_internal (lo, operands[1], operands[2]));
+ emit_move_insn (operands[0], lo);
+ }
else if (TARGET_FIX_R4000)
emit_insn (gen_mul<mode>3_r4000 (operands[0], operands[1], operands[2]));
else
@@ -1398,7 +1406,7 @@
(clobber (match_dup 0))])])
(define_insn "mul<mode>3_internal"
- [(set (match_operand:GPR 0 "register_operand" "=l")
+ [(set (match_operand:GPR 0 "muldiv_target_operand" "=l")
(mult:GPR (match_operand:GPR 1 "register_operand" "d")
(match_operand:GPR 2 "register_operand" "d")))]
"!TARGET_FIX_R4000"
@@ -1575,7 +1583,7 @@
;; Patterns generated by the define_peephole2 below.
(define_insn "*macc2"
- [(set (match_operand:SI 0 "register_operand" "=l")
+ [(set (match_operand:SI 0 "muldiv_target_operand" "=l")
(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "register_operand" "d"))
(match_dup 0)))
@@ -1589,7 +1597,7 @@
(set_attr "mode" "SI")])
(define_insn "*msac2"
- [(set (match_operand:SI 0 "register_operand" "=l")
+ [(set (match_operand:SI 0 "muldiv_target_operand" "=l")
(minus:SI (match_dup 0)
(mult:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "register_operand" "d"))))
@@ -1744,11 +1752,25 @@
DONE;
})
+(define_expand "<u>mulsidi3_32bit_mips16"
+ [(set (match_operand:DI 0 "register_operand")
+ (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
+ (any_extend:DI (match_operand:SI 2 "register_operand"))))]
+ "!TARGET_64BIT && TARGET_MIPS16"
+{
+ rtx hilo;
+
+ hilo = gen_rtx_REG (DImode, MD_REG_FIRST);
+ emit_insn (gen_<u>mulsidi3_32bit (hilo, operands[1], operands[2]));
+ emit_move_insn (operands[0], hilo);
+ DONE;
+})
+
;; As well as being named patterns, these instructions are used by the
;; __builtin_mips_mult<u>() functions. We must always make those functions
;; available if !TARGET_64BIT && ISA_HAS_DSP.
(define_insn "<u>mulsidi3_32bit"
- [(set (match_operand:DI 0 "register_operand" "=ka")
+ [(set (match_operand:DI 0 "muldiv_target_operand" "=ka")
(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
(any_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
"!TARGET_64BIT && (!TARGET_FIX_R4000 || ISA_HAS_DSP)"
@@ -1766,20 +1788,27 @@
(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
(any_extend:DI (match_operand:SI 2 "register_operand" "d"))))
(clobber (match_scratch:DI 3 "=x"))]
- "!TARGET_64BIT && TARGET_FIX_R4000"
+ "!TARGET_64BIT && TARGET_FIX_R4000 && !ISA_HAS_DSP"
"mult<u>\t%1,%2\;mflo\t%L0\;mfhi\t%M0"
[(set_attr "type" "imul")
(set_attr "mode" "SI")
(set_attr "length" "12")])
-(define_insn "<u>mulsidi3_64bit"
+(define_insn_and_split "<u>mulsidi3_64bit"
[(set (match_operand:DI 0 "register_operand" "=d")
(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
(any_extend:DI (match_operand:SI 2 "register_operand" "d"))))
(clobber (match_scratch:TI 3 "=x"))
(clobber (match_scratch:DI 4 "=d"))]
- "TARGET_64BIT && !TARGET_FIX_R4000 && !ISA_HAS_DMUL3"
+ "TARGET_64BIT && !TARGET_FIX_R4000 && !ISA_HAS_DMUL3 && !TARGET_MIPS16"
"#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ emit_insn (gen_<u>mulsidi3_64bit_split (operands[0], operands[1],
+ operands[2], operands[4]));
+ DONE;
+}
[(set_attr "type" "imul")
(set_attr "mode" "SI")
(set (attr "length")
@@ -1787,63 +1816,52 @@
(const_int 16)
(const_int 28)))])
-(define_split
- [(set (match_operand:DI 0 "d_operand")
- (mult:DI (any_extend:DI (match_operand:SI 1 "d_operand"))
- (any_extend:DI (match_operand:SI 2 "d_operand"))))
- (clobber (match_operand:TI 3 "hilo_operand"))
- (clobber (match_operand:DI 4 "d_operand"))]
- "TARGET_64BIT && !TARGET_FIX_R4000 && ISA_HAS_EXT_INS && reload_completed"
- [(set (match_dup 3)
- (unspec:TI [(mult:DI (any_extend:DI (match_dup 1))
- (any_extend:DI (match_dup 2)))]
- UNSPEC_SET_HILO))
-
- ;; OP0 <- LO, OP4 <- HI
- (set (match_dup 0) (match_dup 5))
- (set (match_dup 4) (unspec:DI [(match_dup 3)] UNSPEC_MFHI))
-
- (set (zero_extract:DI (match_dup 0) (const_int 32) (const_int 32))
- (match_dup 4))]
- { operands[5] = gen_rtx_REG (DImode, LO_REGNUM); })
+(define_expand "<u>mulsidi3_64bit_mips16"
+ [(set (match_operand:DI 0 "register_operand")
+ (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
+ (any_extend:DI (match_operand:SI 2 "register_operand"))))]
+ "TARGET_64BIT && TARGET_MIPS16"
+{
+ emit_insn (gen_<u>mulsidi3_64bit_split (operands[0], operands[1],
+ operands[2], gen_reg_rtx (DImode)));
+ DONE;
+})
-(define_split
- [(set (match_operand:DI 0 "d_operand")
- (mult:DI (any_extend:DI (match_operand:SI 1 "d_operand"))
- (any_extend:DI (match_operand:SI 2 "d_operand"))))
- (clobber (match_operand:TI 3 "hilo_operand"))
- (clobber (match_operand:DI 4 "d_operand"))]
- "TARGET_64BIT && !TARGET_FIX_R4000 && !ISA_HAS_EXT_INS && reload_completed"
- [(set (match_dup 3)
- (unspec:TI [(mult:DI (any_extend:DI (match_dup 1))
- (any_extend:DI (match_dup 2)))]
- UNSPEC_SET_HILO))
-
- ;; OP0 <- LO, OP4 <- HI
- (set (match_dup 0) (match_dup 5))
- (set (match_dup 4) (unspec:DI [(match_dup 3)] UNSPEC_MFHI))
-
- ;; Zero-extend OP0.
- (set (match_dup 0)
- (ashift:DI (match_dup 0)
- (const_int 32)))
- (set (match_dup 0)
- (lshiftrt:DI (match_dup 0)
- (const_int 32)))
+(define_expand "<u>mulsidi3_64bit_split"
+ [(set (match_operand:DI 0 "register_operand")
+ (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
+ (any_extend:DI (match_operand:SI 2 "register_operand"))))
+ (clobber (match_operand:DI 3 "register_operand"))]
+ ""
+{
+ rtx hilo;
- ;; Shift OP4 into place.
- (set (match_dup 4)
- (ashift:DI (match_dup 4)
- (const_int 32)))
+ hilo = gen_rtx_REG (TImode, MD_REG_FIRST);
+ emit_insn (gen_<u>mulsidi3_64bit_hilo (hilo, operands[1], operands[2]));
- ;; OR the two halves together
- (set (match_dup 0)
- (ior:DI (match_dup 0)
- (match_dup 4)))]
- { operands[5] = gen_rtx_REG (DImode, LO_REGNUM); })
+ emit_move_insn (operands[0], gen_rtx_REG (DImode, LO_REGNUM));
+ emit_insn (gen_mfhidi_ti (operands[3], hilo));
+
+ if (ISA_HAS_EXT_INS)
+ emit_insn (gen_insvdi (operands[0], GEN_INT (32), GEN_INT (32),
+ operands[3]));
+ else
+ {
+ /* Zero-extend the low part. */
+ mips_emit_binary (ASHIFT, operands[0], operands[0], GEN_INT (32));
+ mips_emit_binary (LSHIFTRT, operands[0], operands[0], GEN_INT (32));
+
+ /* Shift the high part into place. */
+ mips_emit_binary (ASHIFT, operands[3], operands[3], GEN_INT (32));
+
+ /* OR the two halves together. */
+ mips_emit_binary (IOR, operands[0], operands[0], operands[3]);
+ }
+ DONE;
+})
(define_insn "<u>mulsidi3_64bit_hilo"
- [(set (match_operand:TI 0 "register_operand" "=x")
+ [(set (match_operand:TI 0 "muldiv_target_operand" "=x")
(unspec:TI
[(mult:DI
(any_extend:DI (match_operand:SI 1 "register_operand" "d"))
@@ -1867,7 +1885,7 @@
;; Widening multiply with negation.
(define_insn "*muls<u>_di"
- [(set (match_operand:DI 0 "register_operand" "=x")
+ [(set (match_operand:DI 0 "muldiv_target_operand" "=x")
(neg:DI
(mult:DI
(any_extend:DI (match_operand:SI 1 "register_operand" "d"))
@@ -1885,9 +1903,9 @@
;; in GENERATE_MADD_MSUB for -mno-dsp, but always ignore them for -mdsp,
;; even if !ISA_HAS_DSP_MULT.
(define_insn "<u>msubsidi4"
- [(set (match_operand:DI 0 "register_operand" "=ka")
+ [(set (match_operand:DI 0 "muldiv_target_operand" "=ka")
(minus:DI
- (match_operand:DI 3 "register_operand" "0")
+ (match_operand:DI 3 "muldiv_target_operand" "0")
(mult:DI
(any_extend:DI (match_operand:SI 1 "register_operand" "d"))
(any_extend:DI (match_operand:SI 2 "register_operand" "d")))))]
@@ -1918,6 +1936,9 @@
emit_insn (gen_<su>mulsi3_highpart_mulhi_internal (operands[0],
operands[1],
operands[2]));
+ else if (TARGET_MIPS16)
+ emit_insn (gen_<su>mulsi3_highpart_split (operands[0], operands[1],
+ operands[2]));
else
emit_insn (gen_<su>mulsi3_highpart_internal (operands[0], operands[1],
operands[2]));
@@ -1932,11 +1953,28 @@
(any_extend:DI (match_operand:SI 2 "register_operand" "d")))
(const_int 32))))
(clobber (match_scratch:SI 3 "=l"))]
- "!ISA_HAS_MULHI"
+ "!ISA_HAS_MULHI && !TARGET_MIPS16"
{ return TARGET_FIX_R4000 ? "mult<u>\t%1,%2\n\tmfhi\t%0" : "#"; }
"&& reload_completed && !TARGET_FIX_R4000"
[(const_int 0)]
{
+ emit_insn (gen_<su>mulsi3_highpart_split (operands[0], operands[1],
+ operands[2]));
+ DONE;
+}
+ [(set_attr "type" "imul")
+ (set_attr "mode" "SI")
+ (set_attr "length" "8")])
+
+(define_expand "<su>mulsi3_highpart_split"
+ [(set (match_operand:SI 0 "register_operand")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
+ (any_extend:DI (match_operand:SI 2 "register_operand")))
+ (const_int 32))))]
+ ""
+{
rtx hilo;
if (TARGET_64BIT)
@@ -1952,10 +1990,7 @@
emit_insn (gen_mfhisi_di (operands[0], hilo));
}
DONE;
-}
- [(set_attr "type" "imul")
- (set_attr "mode" "SI")
- (set_attr "length" "8")])
+})
(define_insn "<su>mulsi3_highpart_mulhi_internal"
[(set (match_operand:SI 0 "register_operand" "=d")
@@ -1989,7 +2024,25 @@
;; Disable unsigned multiplication for -mfix-vr4120. This is for VR4120
;; errata MD(0), which says that dmultu does not always produce the
;; correct result.
-(define_insn_and_split "<su>muldi3_highpart"
+(define_expand "<su>muldi3_highpart"
+ [(set (match_operand:DI 0 "register_operand")
+ (truncate:DI
+ (lshiftrt:TI
+ (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand"))
+ (any_extend:TI (match_operand:DI 2 "register_operand")))
+ (const_int 64))))]
+ "TARGET_64BIT && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)"
+{
+ if (TARGET_MIPS16)
+ emit_insn (gen_<su>muldi3_highpart_split (operands[0], operands[1],
+ operands[2]));
+ else
+ emit_insn (gen_<su>muldi3_highpart_internal (operands[0], operands[1],
+ operands[2]));
+ DONE;
+})
+
+(define_insn_and_split "<su>muldi3_highpart_internal"
[(set (match_operand:DI 0 "register_operand" "=d")
(truncate:DI
(lshiftrt:TI
@@ -1997,21 +2050,37 @@
(any_extend:TI (match_operand:DI 2 "register_operand" "d")))
(const_int 64))))
(clobber (match_scratch:DI 3 "=l"))]
- "TARGET_64BIT && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)"
+ "TARGET_64BIT
+ && !TARGET_MIPS16
+ && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)"
{ return TARGET_FIX_R4000 ? "dmult<u>\t%1,%2\n\tmfhi\t%0" : "#"; }
"&& reload_completed && !TARGET_FIX_R4000"
[(const_int 0)]
{
+ emit_insn (gen_<su>muldi3_highpart_split (operands[0], operands[1],
+ operands[2]));
+ DONE;
+}
+ [(set_attr "type" "imul")
+ (set_attr "mode" "DI")
+ (set_attr "length" "8")])
+
+(define_expand "<su>muldi3_highpart_split"
+ [(set (match_operand:DI 0 "register_operand")
+ (truncate:DI
+ (lshiftrt:TI
+ (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand"))
+ (any_extend:TI (match_operand:DI 2 "register_operand")))
+ (const_int 64))))]
+ ""
+{
rtx hilo;
hilo = gen_rtx_REG (TImode, MD_REG_FIRST);
emit_insn (gen_<u>mulditi3_internal (hilo, operands[1], operands[2]));
emit_insn (gen_mfhidi_ti (operands[0], hilo));
DONE;
-}
- [(set_attr "type" "imul")
- (set_attr "mode" "DI")
- (set_attr "length" "8")])
+})
(define_expand "<u>mulditi3"
[(set (match_operand:TI 0 "register_operand")
@@ -2019,7 +2088,15 @@
(any_extend:TI (match_operand:DI 2 "register_operand"))))]
"TARGET_64BIT && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)"
{
- if (TARGET_FIX_R4000)
+ rtx hilo;
+
+ if (TARGET_MIPS16)
+ {
+ hilo = gen_rtx_REG (TImode, MD_REG_FIRST);
+ emit_insn (gen_<u>mulditi3_internal (hilo, operands[1], operands[2]));
+ emit_move_insn (operands[0], hilo);
+ }
+ else if (TARGET_FIX_R4000)
emit_insn (gen_<u>mulditi3_r4000 (operands[0], operands[1], operands[2]));
else
emit_insn (gen_<u>mulditi3_internal (operands[0], operands[1],
@@ -2028,7 +2105,7 @@
})
(define_insn "<u>mulditi3_internal"
- [(set (match_operand:TI 0 "register_operand" "=x")
+ [(set (match_operand:TI 0 "muldiv_target_operand" "=x")
(mult:TI (any_extend:TI (match_operand:DI 1 "register_operand" "d"))
(any_extend:TI (match_operand:DI 2 "register_operand" "d"))))]
"TARGET_64BIT
@@ -2067,11 +2144,11 @@
;; See the comment above <u>msubsidi4 for the relationship between
;; ISA_HAS_DSP and ISA_HAS_DSP_MULT.
(define_insn "<u>maddsidi4"
- [(set (match_operand:DI 0 "register_operand" "=ka")
+ [(set (match_operand:DI 0 "muldiv_target_operand" "=ka")
(plus:DI
(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
(any_extend:DI (match_operand:SI 2 "register_operand" "d")))
- (match_operand:DI 3 "register_operand" "0")))]
+ (match_operand:DI 3 "muldiv_target_operand" "0")))]
"(TARGET_MAD || ISA_HAS_MACC || GENERATE_MADD_MSUB || ISA_HAS_DSP)
&& !TARGET_64BIT"
{
@@ -2311,72 +2388,113 @@
;; VR4120 errata MD(A1): signed division instructions do not work correctly
;; with negative operands. We use special libgcc functions instead.
-(define_insn_and_split "divmod<mode>4"
- [(set (match_operand:GPR 0 "register_operand" "=l")
+(define_expand "divmod<mode>4"
+ [(set (match_operand:GPR 0 "register_operand")
+ (div:GPR (match_operand:GPR 1 "register_operand")
+ (match_operand:GPR 2 "register_operand")))
+ (set (match_operand:GPR 3 "register_operand")
+ (mod:GPR (match_dup 1)
+ (match_dup 2)))]
+ "!TARGET_FIX_VR4120"
+{
+ if (TARGET_MIPS16)
+ {
+ emit_insn (gen_divmod<mode>4_split (operands[3], operands[1],
+ operands[2]));
+ emit_move_insn (operands[0], gen_rtx_REG (<MODE>mode, LO_REGNUM));
+ }
+ else
+ emit_insn (gen_divmod<mode>4_internal (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+})
+
+(define_insn_and_split "divmod<mode>4_internal"
+ [(set (match_operand:GPR 0 "muldiv_target_operand" "=l")
(div:GPR (match_operand:GPR 1 "register_operand" "d")
(match_operand:GPR 2 "register_operand" "d")))
(set (match_operand:GPR 3 "register_operand" "=d")
(mod:GPR (match_dup 1)
(match_dup 2)))]
- "!TARGET_FIX_VR4120"
+ "!TARGET_FIX_VR4120 && !TARGET_MIPS16"
"#"
"&& reload_completed"
[(const_int 0)]
{
- rtx hilo;
-
- if (TARGET_64BIT)
- {
- hilo = gen_rtx_REG (TImode, MD_REG_FIRST);
- emit_insn (gen_divmod<mode>4_hilo_ti (hilo, operands[1], operands[2]));
- emit_insn (gen_mfhi<mode>_ti (operands[3], hilo));
- }
- else
- {
- hilo = gen_rtx_REG (DImode, MD_REG_FIRST);
- emit_insn (gen_divmod<mode>4_hilo_di (hilo, operands[1], operands[2]));
- emit_insn (gen_mfhi<mode>_di (operands[3], hilo));
- }
+ emit_insn (gen_divmod<mode>4_split (operands[3], operands[1], operands[2]));
DONE;
}
[(set_attr "type" "idiv")
(set_attr "mode" "<MODE>")
(set_attr "length" "8")])
-(define_insn_and_split "udivmod<mode>4"
- [(set (match_operand:GPR 0 "register_operand" "=l")
+(define_expand "udivmod<mode>4"
+ [(set (match_operand:GPR 0 "register_operand")
+ (udiv:GPR (match_operand:GPR 1 "register_operand")
+ (match_operand:GPR 2 "register_operand")))
+ (set (match_operand:GPR 3 "register_operand")
+ (umod:GPR (match_dup 1)
+ (match_dup 2)))]
+ ""
+{
+ if (TARGET_MIPS16)
+ {
+ emit_insn (gen_udivmod<mode>4_split (operands[3], operands[1],
+ operands[2]));
+ emit_move_insn (operands[0], gen_rtx_REG (<MODE>mode, LO_REGNUM));
+ }
+ else
+ emit_insn (gen_udivmod<mode>4_internal (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+})
+
+(define_insn_and_split "udivmod<mode>4_internal"
+ [(set (match_operand:GPR 0 "muldiv_target_operand" "=l")
(udiv:GPR (match_operand:GPR 1 "register_operand" "d")
(match_operand:GPR 2 "register_operand" "d")))
(set (match_operand:GPR 3 "register_operand" "=d")
(umod:GPR (match_dup 1)
(match_dup 2)))]
- ""
+ "!TARGET_MIPS16"
"#"
"reload_completed"
[(const_int 0)]
{
+ emit_insn (gen_udivmod<mode>4_split (operands[3], operands[1], operands[2]));
+ DONE;
+}
+ [(set_attr "type" "idiv")
+ (set_attr "mode" "<MODE>")
+ (set_attr "length" "8")])
+
+(define_expand "<u>divmod<mode>4_split"
+ [(set (match_operand:GPR 0 "register_operand")
+ (any_mod:GPR (match_operand:GPR 1 "register_operand")
+ (match_operand:GPR 2 "register_operand")))]
+ ""
+{
rtx hilo;
if (TARGET_64BIT)
{
hilo = gen_rtx_REG (TImode, MD_REG_FIRST);
- emit_insn (gen_udivmod<mode>4_hilo_ti (hilo, operands[1], operands[2]));
- emit_insn (gen_mfhi<mode>_ti (operands[3], hilo));
+ emit_insn (gen_<u>divmod<mode>4_hilo_ti (hilo, operands[1],
+ operands[2]));
+ emit_insn (gen_mfhi<mode>_ti (operands[0], hilo));
}
else
{
hilo = gen_rtx_REG (DImode, MD_REG_FIRST);
- emit_insn (gen_udivmod<mode>4_hilo_di (hilo, operands[1], operands[2]));
- emit_insn (gen_mfhi<mode>_di (operands[3], hilo));
+ emit_insn (gen_<u>divmod<mode>4_hilo_di (hilo, operands[1],
+ operands[2]));
+ emit_insn (gen_mfhi<mode>_di (operands[0], hilo));
}
DONE;
-}
- [(set_attr "type" "idiv")
- (set_attr "mode" "<MODE>")
- (set_attr "length" "8")])
+})
(define_insn "<u>divmod<GPR:mode>4_hilo_<HILO:mode>"
- [(set (match_operand:HILO 0 "register_operand" "=x")
+ [(set (match_operand:HILO 0 "muldiv_target_operand" "=x")
(unspec:HILO
[(any_div:GPR (match_operand:GPR 1 "register_operand" "d")
(match_operand:GPR 2 "register_operand" "d"))]
@@ -4590,7 +4708,7 @@
;; and the errata related to -mfix-vr4130.
(define_insn "mfhi<GPR:mode>_<HILO:mode>"
[(set (match_operand:GPR 0 "register_operand" "=d")
- (unspec:GPR [(match_operand:HILO 1 "register_operand" "x")]
+ (unspec:GPR [(match_operand:HILO 1 "hilo_operand" "x")]
UNSPEC_MFHI))]
""
{ return ISA_HAS_MACCHI ? "<GPR:d>macchi\t%0,%.,%." : "mfhi\t%0"; }
diff --git a/gcc/config/mips/predicates.md b/gcc/config/mips/predicates.md
index dd5148067cd..5e9398e69f3 100644
--- a/gcc/config/mips/predicates.md
+++ b/gcc/config/mips/predicates.md
@@ -127,6 +127,11 @@
(and (match_code "reg,subreg")
(match_test "ST_REG_P (true_regnum (op))")))
+(define_predicate "muldiv_target_operand"
+ (if_then_else (match_test "TARGET_MIPS16")
+ (match_operand 0 "hilo_operand")
+ (match_operand 0 "register_operand")))
+
(define_special_predicate "pc_or_label_operand"
(match_code "pc,label_ref"))
@@ -189,7 +194,9 @@
})
(define_predicate "move_operand"
- (match_operand 0 "general_operand")
+ ;; Allow HI and LO to be used as the source of a MIPS16 move.
+ (ior (match_operand 0 "general_operand")
+ (match_operand 0 "hilo_operand"))
{
enum mips_symbol_type symbol_type;
diff --git a/gcc/config/pa/pa-linux.h b/gcc/config/pa/pa-linux.h
index addc0e18c8b..6cc68a5c6e1 100644
--- a/gcc/config/pa/pa-linux.h
+++ b/gcc/config/pa/pa-linux.h
@@ -133,7 +133,6 @@ along with GCC; see the file COPYING3. If not see
} \
while (0)
-/* Linux always uses gas. */
#undef TARGET_GAS
#define TARGET_GAS 1
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 23d2d2aa389..af4c95488de 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -103,13 +103,9 @@ extern rtx rs6000_emit_set_const (rtx, enum machine_mode, rtx, int);
extern int rs6000_emit_cmove (rtx, rtx, rtx, rtx);
extern int rs6000_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx);
extern void rs6000_emit_minmax (rtx, enum rtx_code, rtx, rtx);
-extern void rs6000_emit_sync (enum rtx_code, enum machine_mode,
- rtx, rtx, rtx, rtx, bool);
-extern void rs6000_split_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
-extern void rs6000_split_compare_and_swap (rtx, rtx, rtx, rtx, rtx);
-extern void rs6000_expand_compare_and_swapqhi (rtx, rtx, rtx, rtx);
-extern void rs6000_split_compare_and_swapqhi (rtx, rtx, rtx, rtx, rtx, rtx);
-extern void rs6000_split_lock_test_and_set (rtx, rtx, rtx, rtx);
+extern void rs6000_expand_atomic_compare_and_swap (rtx op[]);
+extern void rs6000_expand_atomic_exchange (rtx op[]);
+extern void rs6000_expand_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
extern void rs6000_emit_swdiv (rtx, rtx, rtx, bool);
extern void rs6000_emit_swrsqrt (rtx, rtx);
extern void output_toc (FILE *, rtx, int, enum machine_mode);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 87c84d9844e..f01353b8942 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -17133,199 +17133,6 @@ rs6000_emit_minmax (rtx dest, enum rtx_code code, rtx op0, rtx op1)
emit_move_insn (dest, target);
}
-/* Emit instructions to perform a load-reserved/store-conditional operation.
- The operation performed is an atomic
- (set M (CODE:MODE M OP))
- If not NULL, BEFORE is atomically set to M before the operation, and
- AFTER is set to M after the operation (that is, (CODE:MODE M OP)).
- If SYNC_P then a memory barrier is emitted before the operation.
- Either OP or M may be wrapped in a NOT operation. */
-
-void
-rs6000_emit_sync (enum rtx_code code, enum machine_mode mode,
- rtx m, rtx op, rtx before_param, rtx after_param,
- bool sync_p)
-{
- enum machine_mode used_mode;
- rtx the_op, set_before, set_after, set_atomic, cc_scratch, before, after;
- rtx used_m;
- rtvec vec;
- HOST_WIDE_INT imask = GET_MODE_MASK (mode);
- rtx shift = NULL_RTX;
-
- if (sync_p)
- emit_insn (gen_lwsync ());
-
- used_m = m;
-
- /* If this is smaller than SImode, we'll have to use SImode with
- adjustments. */
- if (mode == QImode || mode == HImode)
- {
- rtx newop, oldop;
-
- if (MEM_ALIGN (used_m) >= 32)
- {
- int ishift = 0;
- if (BYTES_BIG_ENDIAN)
- ishift = GET_MODE_BITSIZE (SImode) - GET_MODE_BITSIZE (mode);
-
- shift = GEN_INT (ishift);
- used_m = change_address (used_m, SImode, 0);
- }
- else
- {
- rtx addrSI, aligned_addr;
- int shift_mask = mode == QImode ? 0x18 : 0x10;
-
- addrSI = gen_lowpart_common (SImode,
- force_reg (Pmode, XEXP (used_m, 0)));
- addrSI = force_reg (SImode, addrSI);
- shift = gen_reg_rtx (SImode);
-
- emit_insn (gen_rlwinm (shift, addrSI, GEN_INT (3),
- GEN_INT (shift_mask)));
- emit_insn (gen_xorsi3 (shift, shift, GEN_INT (shift_mask)));
-
- aligned_addr = expand_binop (Pmode, and_optab,
- XEXP (used_m, 0),
- GEN_INT (-4), NULL_RTX,
- 1, OPTAB_LIB_WIDEN);
- used_m = change_address (used_m, SImode, aligned_addr);
- set_mem_align (used_m, 32);
- }
- /* It's safe to keep the old alias set of USED_M, because
- the operation is atomic and only affects the original
- USED_M. */
- m = used_m;
-
- if (GET_CODE (op) == NOT)
- {
- oldop = lowpart_subreg (SImode, XEXP (op, 0), mode);
- oldop = gen_rtx_NOT (SImode, oldop);
- }
- else
- oldop = lowpart_subreg (SImode, op, mode);
-
- switch (code)
- {
- case IOR:
- case XOR:
- newop = expand_binop (SImode, and_optab,
- oldop, GEN_INT (imask), NULL_RTX,
- 1, OPTAB_LIB_WIDEN);
- emit_insn (gen_ashlsi3 (newop, newop, shift));
- break;
-
- case NOT: /* NAND */
- newop = expand_binop (SImode, ior_optab,
- oldop, GEN_INT (~imask), NULL_RTX,
- 1, OPTAB_LIB_WIDEN);
- emit_insn (gen_rotlsi3 (newop, newop, shift));
- break;
-
- case AND:
- newop = expand_binop (SImode, ior_optab,
- oldop, GEN_INT (~imask), NULL_RTX,
- 1, OPTAB_LIB_WIDEN);
- emit_insn (gen_rotlsi3 (newop, newop, shift));
- break;
-
- case PLUS:
- case MINUS:
- {
- rtx mask;
-
- newop = expand_binop (SImode, and_optab,
- oldop, GEN_INT (imask), NULL_RTX,
- 1, OPTAB_LIB_WIDEN);
- emit_insn (gen_ashlsi3 (newop, newop, shift));
-
- mask = gen_reg_rtx (SImode);
- emit_move_insn (mask, GEN_INT (imask));
- emit_insn (gen_ashlsi3 (mask, mask, shift));
-
- if (code == PLUS)
- newop = gen_rtx_PLUS (SImode, m, newop);
- else
- newop = gen_rtx_MINUS (SImode, m, newop);
- newop = gen_rtx_AND (SImode, newop, mask);
- newop = gen_rtx_IOR (SImode, newop,
- gen_rtx_AND (SImode,
- gen_rtx_NOT (SImode, mask),
- m));
- break;
- }
-
- default:
- gcc_unreachable ();
- }
-
- op = newop;
- used_mode = SImode;
- before = gen_reg_rtx (used_mode);
- after = gen_reg_rtx (used_mode);
- }
- else
- {
- used_mode = mode;
- before = before_param;
- after = after_param;
-
- if (before == NULL_RTX)
- before = gen_reg_rtx (used_mode);
- if (after == NULL_RTX)
- after = gen_reg_rtx (used_mode);
- }
-
- if ((code == PLUS || code == MINUS)
- && used_mode != mode)
- the_op = op; /* Computed above. */
- else if (GET_CODE (op) == NOT && GET_CODE (m) != NOT)
- the_op = gen_rtx_fmt_ee (code, used_mode, op, m);
- else if (code == NOT)
- the_op = gen_rtx_fmt_ee (IOR, used_mode,
- gen_rtx_NOT (used_mode, m),
- gen_rtx_NOT (used_mode, op));
- else
- the_op = gen_rtx_fmt_ee (code, used_mode, m, op);
-
- set_after = gen_rtx_SET (VOIDmode, after, the_op);
- set_before = gen_rtx_SET (VOIDmode, before, used_m);
- set_atomic = gen_rtx_SET (VOIDmode, used_m,
- gen_rtx_UNSPEC (used_mode,
- gen_rtvec (1, the_op),
- UNSPEC_SYNC_OP));
- cc_scratch = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (CCmode));
-
- if ((code == PLUS || code == MINUS) && used_mode != mode)
- vec = gen_rtvec (5, set_after, set_before, set_atomic, cc_scratch,
- gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode)));
- else
- vec = gen_rtvec (4, set_after, set_before, set_atomic, cc_scratch);
- emit_insn (gen_rtx_PARALLEL (VOIDmode, vec));
-
- /* Shift and mask the return values properly. */
- if (used_mode != mode && before_param)
- {
- emit_insn (gen_lshrsi3 (before, before, shift));
- convert_move (before_param, before, 1);
- }
-
- if (used_mode != mode && after_param)
- {
- emit_insn (gen_lshrsi3 (after, after, shift));
- convert_move (after_param, after, 1);
- }
-
- /* The previous sequence will end with a branch that's dependent on
- the conditional store, so placing an isync will ensure that no
- other instructions (especially, no load or store instructions)
- can start before the atomic operation completes. */
- if (sync_p)
- emit_insn (gen_isync ());
-}
-
/* A subroutine of the atomic operation splitters. Jump to LABEL if
COND is true. Mark the jump as unlikely to be taken. */
@@ -17347,10 +17154,18 @@ static void
emit_load_locked (enum machine_mode mode, rtx reg, rtx mem)
{
rtx (*fn) (rtx, rtx) = NULL;
- if (mode == SImode)
- fn = gen_load_locked_si;
- else if (mode == DImode)
- fn = gen_load_locked_di;
+
+ switch (mode)
+ {
+ case SImode:
+ fn = gen_load_lockedsi;
+ break;
+ case DImode:
+ fn = gen_load_lockeddi;
+ break;
+ default:
+ gcc_unreachable ();
+ }
emit_insn (fn (reg, mem));
}
@@ -17361,214 +17176,406 @@ static void
emit_store_conditional (enum machine_mode mode, rtx res, rtx mem, rtx val)
{
rtx (*fn) (rtx, rtx, rtx) = NULL;
- if (mode == SImode)
- fn = gen_store_conditional_si;
- else if (mode == DImode)
- fn = gen_store_conditional_di;
+
+ switch (mode)
+ {
+ case SImode:
+ fn = gen_store_conditionalsi;
+ break;
+ case DImode:
+ fn = gen_store_conditionaldi;
+ break;
+ default:
+ gcc_unreachable ();
+ }
/* Emit sync before stwcx. to address PPC405 Erratum. */
if (PPC405_ERRATUM77)
- emit_insn (gen_memory_barrier ());
+ emit_insn (gen_hwsync ());
emit_insn (fn (res, mem, val));
}
-/* Expand an atomic fetch-and-operate pattern. CODE is the binary operation
- to perform. MEM is the memory on which to operate. VAL is the second
- operand of the binary operator. BEFORE and AFTER are optional locations to
- return the value of MEM either before of after the operation. SCRATCH is
- a scratch register. */
+/* Expand barriers before and after a load_locked/store_cond sequence. */
-void
-rs6000_split_atomic_op (enum rtx_code code, rtx mem, rtx val,
- rtx before, rtx after, rtx scratch)
+static void
+rs6000_pre_atomic_barrier (enum memmodel model)
{
- enum machine_mode mode = GET_MODE (mem);
- rtx label, x, cond = gen_rtx_REG (CCmode, CR0_REGNO);
+ switch (model)
+ {
+ case MEMMODEL_RELAXED:
+ case MEMMODEL_CONSUME:
+ case MEMMODEL_ACQUIRE:
+ break;
+ case MEMMODEL_RELEASE:
+ case MEMMODEL_ACQ_REL:
+ emit_insn (gen_lwsync ());
+ break;
+ case MEMMODEL_SEQ_CST:
+ emit_insn (gen_hwsync ());
+ break;
+ default:
+ gcc_unreachable ();
+ }
+}
- emit_insn (gen_lwsync ());
+static void
+rs6000_post_atomic_barrier (enum memmodel model)
+{
+ switch (model)
+ {
+ case MEMMODEL_RELAXED:
+ case MEMMODEL_CONSUME:
+ case MEMMODEL_RELEASE:
+ break;
+ case MEMMODEL_ACQUIRE:
+ case MEMMODEL_ACQ_REL:
+ case MEMMODEL_SEQ_CST:
+ emit_insn (gen_isync ());
+ break;
+ default:
+ gcc_unreachable ();
+ }
+}
- label = gen_label_rtx ();
- emit_label (label);
- label = gen_rtx_LABEL_REF (VOIDmode, label);
+/* A subroutine of the various atomic expanders. For sub-word operations,
+ we must adjust things to operate on SImode. Given the original MEM,
+ return a new aligned memory. Also build and return the quantities by
+ which to shift and mask. */
- if (before == NULL_RTX)
- before = scratch;
- emit_load_locked (mode, before, mem);
+static rtx
+rs6000_adjust_atomic_subword (rtx orig_mem, rtx *pshift, rtx *pmask)
+{
+ rtx addr, align, shift, mask, mem;
+ HOST_WIDE_INT shift_mask;
+ enum machine_mode mode = GET_MODE (orig_mem);
- if (code == NOT)
- x = gen_rtx_IOR (mode,
- gen_rtx_NOT (mode, before),
- gen_rtx_NOT (mode, val));
- else if (code == AND)
- x = gen_rtx_UNSPEC (mode, gen_rtvec (2, before, val), UNSPEC_AND);
- else
- x = gen_rtx_fmt_ee (code, mode, before, val);
+ /* For smaller modes, we have to implement this via SImode. */
+ shift_mask = (mode == QImode ? 0x18 : 0x10);
- if (after != NULL_RTX)
- emit_insn (gen_rtx_SET (VOIDmode, after, copy_rtx (x)));
- emit_insn (gen_rtx_SET (VOIDmode, scratch, x));
+ addr = XEXP (orig_mem, 0);
+ addr = force_reg (GET_MODE (addr), addr);
- emit_store_conditional (mode, cond, mem, scratch);
+ /* Aligned memory containing subword. Generate a new memory. We
+ do not want any of the existing MEM_ATTR data, as we're now
+ accessing memory outside the original object. */
+ align = expand_simple_binop (Pmode, AND, addr, GEN_INT (-4),
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
+ mem = gen_rtx_MEM (SImode, align);
+ MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (orig_mem);
+ if (MEM_ALIAS_SET (orig_mem) == ALIAS_SET_MEMORY_BARRIER)
+ set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
- x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
- emit_unlikely_jump (x, label);
+ /* Shift amount for subword relative to aligned word. */
+ shift = gen_reg_rtx (SImode);
+ addr = gen_lowpart (SImode, addr);
+ emit_insn (gen_rlwinm (shift, addr, GEN_INT (3), GEN_INT (shift_mask)));
+ shift = expand_simple_binop (SImode, XOR, shift, GEN_INT (shift_mask),
+ shift, 1, OPTAB_LIB_WIDEN);
+ *pshift = shift;
+
+ /* Mask for insertion. */
+ mask = expand_simple_binop (SImode, ASHIFT, GEN_INT (GET_MODE_MASK (mode)),
+ shift, NULL_RTX, 1, OPTAB_LIB_WIDEN);
+ *pmask = mask;
- emit_insn (gen_isync ());
+ return mem;
}
-/* Expand an atomic compare and swap operation. MEM is the memory on which
- to operate. OLDVAL is the old value to be compared. NEWVAL is the new
- value to be stored. SCRATCH is a scratch GPR. */
+/* A subroutine of the various atomic expanders. For sub-word operands,
+ combine OLDVAL and NEWVAL via MASK. Returns a new pseduo. */
+
+static rtx
+rs6000_mask_atomic_subword (rtx oldval, rtx newval, rtx mask)
+{
+ rtx x;
+
+ x = gen_reg_rtx (SImode);
+ emit_insn (gen_rtx_SET (VOIDmode, x,
+ gen_rtx_AND (SImode,
+ gen_rtx_NOT (SImode, mask),
+ oldval)));
+
+ x = expand_simple_binop (SImode, IOR, newval, x, x, 1, OPTAB_LIB_WIDEN);
+
+ return x;
+}
+
+/* A subroutine of the various atomic expanders. For sub-word operands,
+ extract WIDE to NARROW via SHIFT. */
+
+static void
+rs6000_finish_atomic_subword (rtx narrow, rtx wide, rtx shift)
+{
+ wide = expand_simple_binop (SImode, LSHIFTRT, wide, shift,
+ wide, 1, OPTAB_LIB_WIDEN);
+ emit_move_insn (narrow, gen_lowpart (GET_MODE (narrow), wide));
+}
+
+/* Expand an atomic compare and swap operation. */
void
-rs6000_split_compare_and_swap (rtx retval, rtx mem, rtx oldval, rtx newval,
- rtx scratch)
+rs6000_expand_atomic_compare_and_swap (rtx operands[])
{
- enum machine_mode mode = GET_MODE (mem);
- rtx label1, label2, x, cond = gen_rtx_REG (CCmode, CR0_REGNO);
+ rtx boolval, retval, mem, oldval, newval, cond;
+ rtx label1, label2, x, mask, shift;
+ enum machine_mode mode;
+ enum memmodel mod_s, mod_f;
+ bool is_weak;
+
+ boolval = operands[0];
+ retval = operands[1];
+ mem = operands[2];
+ oldval = operands[3];
+ newval = operands[4];
+ is_weak = (INTVAL (operands[5]) != 0);
+ mod_s = (enum memmodel) INTVAL (operands[6]);
+ mod_f = (enum memmodel) INTVAL (operands[7]);
+ mode = GET_MODE (mem);
+
+ mask = shift = NULL_RTX;
+ if (mode == QImode || mode == HImode)
+ {
+ mem = rs6000_adjust_atomic_subword (mem, &shift, &mask);
+
+ /* Shift and mask OLDVAL into position with the word. */
+ oldval = convert_modes (SImode, mode, oldval, 1);
+ oldval = expand_simple_binop (SImode, ASHIFT, oldval, shift,
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
- emit_insn (gen_lwsync ());
+ /* Shift and mask NEWVAL into position within the word. */
+ newval = convert_modes (SImode, mode, newval, 1);
+ newval = expand_simple_binop (SImode, ASHIFT, newval, shift,
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
- label1 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+ /* Prepare to adjust the return value. */
+ retval = gen_reg_rtx (SImode);
+ mode = SImode;
+ }
+
+ rs6000_pre_atomic_barrier (mod_s);
+
+ emit_move_insn (boolval, const0_rtx);
+
+ label1 = NULL_RTX;
+ if (!is_weak)
+ {
+ label1 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+ emit_label (XEXP (label1, 0));
+ }
label2 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
- emit_label (XEXP (label1, 0));
emit_load_locked (mode, retval, mem);
- x = gen_rtx_COMPARE (CCmode, retval, oldval);
- emit_insn (gen_rtx_SET (VOIDmode, cond, x));
+ x = retval;
+ if (mask)
+ {
+ x = expand_simple_binop (SImode, AND, retval, mask,
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
+ }
- x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
+ x = gen_rtx_NE (VOIDmode, x, oldval);
+ x = rs6000_generate_compare (x, mode);
emit_unlikely_jump (x, label2);
- emit_move_insn (scratch, newval);
- emit_store_conditional (mode, cond, mem, scratch);
+ x = newval;
+ if (mask)
+ x = rs6000_mask_atomic_subword (retval, newval, mask);
- x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
- emit_unlikely_jump (x, label1);
+ cond = gen_reg_rtx (CCmode);
+ emit_store_conditional (mode, cond, mem, x);
+
+ if (is_weak)
+ {
+ /* ??? It's either this or an unlikely jump over (set bool 1). */
+ x = gen_rtx_EQ (SImode, cond, const0_rtx);
+ emit_insn (gen_rtx_SET (VOIDmode, boolval, x));
+ }
+ else
+ {
+ x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
+ emit_unlikely_jump (x, label1);
+ emit_move_insn (boolval, const1_rtx);
+ }
+
+ if (mod_f != MEMMODEL_RELAXED)
+ emit_label (XEXP (label2, 0));
- emit_insn (gen_isync ());
- emit_label (XEXP (label2, 0));
+ rs6000_post_atomic_barrier (mod_s);
+
+ if (mod_f == MEMMODEL_RELAXED)
+ emit_label (XEXP (label2, 0));
+
+ if (shift)
+ rs6000_finish_atomic_subword (operands[1], retval, shift);
}
-/* Expand an atomic test and set operation. MEM is the memory on which
- to operate. VAL is the value set. SCRATCH is a scratch GPR. */
+/* Expand an atomic exchange operation. */
void
-rs6000_split_lock_test_and_set (rtx retval, rtx mem, rtx val, rtx scratch)
+rs6000_expand_atomic_exchange (rtx operands[])
{
- enum machine_mode mode = GET_MODE (mem);
- rtx label, x, cond = gen_rtx_REG (CCmode, CR0_REGNO);
+ rtx retval, mem, val, cond;
+ enum machine_mode mode;
+ enum memmodel model;
+ rtx label, x, mask, shift;
+
+ retval = operands[0];
+ mem = operands[1];
+ val = operands[2];
+ model = (enum memmodel) INTVAL (operands[3]);
+ mode = GET_MODE (mem);
+
+ mask = shift = NULL_RTX;
+ if (mode == QImode || mode == HImode)
+ {
+ mem = rs6000_adjust_atomic_subword (mem, &shift, &mask);
+
+ /* Shift and mask VAL into position with the word. */
+ val = convert_modes (SImode, mode, val, 1);
+ val = expand_simple_binop (SImode, ASHIFT, val, shift,
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
+
+ /* Prepare to adjust the return value. */
+ retval = gen_reg_rtx (SImode);
+ mode = SImode;
+ }
+
+ rs6000_pre_atomic_barrier (model);
label = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
emit_label (XEXP (label, 0));
emit_load_locked (mode, retval, mem);
- emit_move_insn (scratch, val);
- emit_store_conditional (mode, cond, mem, scratch);
+
+ x = val;
+ if (mask)
+ x = rs6000_mask_atomic_subword (retval, val, mask);
+
+ cond = gen_reg_rtx (CCmode);
+ emit_store_conditional (mode, cond, mem, x);
x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
emit_unlikely_jump (x, label);
- emit_insn (gen_isync ());
+ rs6000_post_atomic_barrier (model);
+
+ if (shift)
+ rs6000_finish_atomic_subword (operands[0], retval, shift);
}
+/* Expand an atomic fetch-and-operate pattern. CODE is the binary operation
+ to perform. MEM is the memory on which to operate. VAL is the second
+ operand of the binary operator. BEFORE and AFTER are optional locations to
+ return the value of MEM either before of after the operation. MODEL_RTX
+ is a CONST_INT containing the memory model to use. */
+
void
-rs6000_expand_compare_and_swapqhi (rtx dst, rtx mem, rtx oldval, rtx newval)
+rs6000_expand_atomic_op (enum rtx_code code, rtx mem, rtx val,
+ rtx orig_before, rtx orig_after, rtx model_rtx)
{
+ enum memmodel model = (enum memmodel) INTVAL (model_rtx);
enum machine_mode mode = GET_MODE (mem);
- rtx addrSI, align, wdst, shift, mask;
- HOST_WIDE_INT shift_mask = mode == QImode ? 0x18 : 0x10;
- HOST_WIDE_INT imask = GET_MODE_MASK (mode);
+ rtx label, x, cond, mask, shift;
+ rtx before = orig_before, after = orig_after;
- /* Shift amount for subword relative to aligned word. */
- addrSI = force_reg (GET_MODE (XEXP (mem, 0)), XEXP (mem, 0));
- addrSI = force_reg (SImode, gen_lowpart_common (SImode, addrSI));
- shift = gen_reg_rtx (SImode);
- emit_insn (gen_rlwinm (shift, addrSI, GEN_INT (3),
- GEN_INT (shift_mask)));
- emit_insn (gen_xorsi3 (shift, shift, GEN_INT (shift_mask)));
-
- /* Shift and mask old value into position within word. */
- oldval = convert_modes (SImode, mode, oldval, 1);
- oldval = expand_binop (SImode, and_optab,
- oldval, GEN_INT (imask), NULL_RTX,
- 1, OPTAB_LIB_WIDEN);
- emit_insn (gen_ashlsi3 (oldval, oldval, shift));
-
- /* Shift and mask new value into position within word. */
- newval = convert_modes (SImode, mode, newval, 1);
- newval = expand_binop (SImode, and_optab,
- newval, GEN_INT (imask), NULL_RTX,
- 1, OPTAB_LIB_WIDEN);
- emit_insn (gen_ashlsi3 (newval, newval, shift));
+ mask = shift = NULL_RTX;
+ if (mode == QImode || mode == HImode)
+ {
+ mem = rs6000_adjust_atomic_subword (mem, &shift, &mask);
- /* Mask for insertion. */
- mask = gen_reg_rtx (SImode);
- emit_move_insn (mask, GEN_INT (imask));
- emit_insn (gen_ashlsi3 (mask, mask, shift));
+ /* Shift and mask VAL into position with the word. */
+ val = convert_modes (SImode, mode, val, 1);
+ val = expand_simple_binop (SImode, ASHIFT, val, shift,
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
- /* Address of aligned word containing subword. */
- align = expand_binop (Pmode, and_optab, XEXP (mem, 0), GEN_INT (-4),
- NULL_RTX, 1, OPTAB_LIB_WIDEN);
- mem = change_address (mem, SImode, align);
- set_mem_align (mem, 32);
- MEM_VOLATILE_P (mem) = 1;
+ switch (code)
+ {
+ case IOR:
+ case XOR:
+ /* We've already zero-extended VAL. That is sufficient to
+ make certain that it does not affect other bits. */
+ mask = NULL;
+ break;
- wdst = gen_reg_rtx (SImode);
- emit_insn (gen_sync_compare_and_swapqhi_internal (wdst, mask,
- oldval, newval, mem));
+ case AND:
+ /* If we make certain that all of the other bits in VAL are
+ set, that will be sufficient to not affect other bits. */
+ x = gen_rtx_NOT (SImode, mask);
+ x = gen_rtx_IOR (SImode, x, val);
+ emit_insn (gen_rtx_SET (VOIDmode, val, x));
+ mask = NULL;
+ break;
- /* Shift the result back. */
- emit_insn (gen_lshrsi3 (wdst, wdst, shift));
+ case NOT:
+ case PLUS:
+ case MINUS:
+ /* These will all affect bits outside the field and need
+ adjustment via MASK within the loop. */
+ break;
- emit_move_insn (dst, gen_lowpart (mode, wdst));
-}
+ default:
+ gcc_unreachable ();
+ }
-void
-rs6000_split_compare_and_swapqhi (rtx dest, rtx mask,
- rtx oldval, rtx newval, rtx mem,
- rtx scratch)
-{
- rtx label1, label2, x, cond = gen_rtx_REG (CCmode, CR0_REGNO);
+ /* Prepare to adjust the return value. */
+ before = gen_reg_rtx (SImode);
+ if (after)
+ after = gen_reg_rtx (SImode);
+ mode = SImode;
+ }
- emit_insn (gen_lwsync ());
- label1 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
- label2 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
- emit_label (XEXP (label1, 0));
+ rs6000_pre_atomic_barrier (model);
- emit_load_locked (SImode, scratch, mem);
+ label = gen_label_rtx ();
+ emit_label (label);
+ label = gen_rtx_LABEL_REF (VOIDmode, label);
- /* Mask subword within loaded value for comparison with oldval.
- Use UNSPEC_AND to avoid clobber.*/
- emit_insn (gen_rtx_SET (SImode, dest,
- gen_rtx_UNSPEC (SImode,
- gen_rtvec (2, scratch, mask),
- UNSPEC_AND)));
+ if (before == NULL_RTX)
+ before = gen_reg_rtx (mode);
- x = gen_rtx_COMPARE (CCmode, dest, oldval);
- emit_insn (gen_rtx_SET (VOIDmode, cond, x));
+ emit_load_locked (mode, before, mem);
- x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
- emit_unlikely_jump (x, label2);
+ if (code == NOT)
+ {
+ x = expand_simple_binop (mode, AND, before, val,
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
+ after = expand_simple_unop (mode, NOT, x, after, 1);
+ }
+ else
+ {
+ after = expand_simple_binop (mode, code, before, val,
+ after, 1, OPTAB_LIB_WIDEN);
+ }
- /* Clear subword within loaded value for insertion of new value. */
- emit_insn (gen_rtx_SET (SImode, scratch,
- gen_rtx_AND (SImode,
- gen_rtx_NOT (SImode, mask), scratch)));
- emit_insn (gen_iorsi3 (scratch, scratch, newval));
- emit_store_conditional (SImode, cond, mem, scratch);
+ x = after;
+ if (mask)
+ {
+ x = expand_simple_binop (SImode, AND, after, mask,
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
+ x = rs6000_mask_atomic_subword (before, x, mask);
+ }
+
+ cond = gen_reg_rtx (CCmode);
+ emit_store_conditional (mode, cond, mem, x);
x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
- emit_unlikely_jump (x, label1);
+ emit_unlikely_jump (x, label);
- emit_insn (gen_isync ());
- emit_label (XEXP (label2, 0));
-}
+ rs6000_post_atomic_barrier (model);
+ if (shift)
+ {
+ if (orig_before)
+ rs6000_finish_atomic_subword (orig_before, before, shift);
+ if (orig_after)
+ rs6000_finish_atomic_subword (orig_after, after, shift);
+ }
+ else if (orig_after && after != orig_after)
+ emit_move_insn (orig_after, after);
+}
- /* Emit instructions to move SRC to DST. Called by splitters for
+/* Emit instructions to move SRC to DST. Called by splitters for
multi-register moves. It will emit at most one instruction for
each register that is accessed; that is, it won't emit li/lis pairs
(or equivalent for 64-bit code). One of SRC or DST must be a hard
@@ -25777,7 +25784,7 @@ rs6000_xcoff_section_type_flags (tree decl, const char *name, int reloc)
unsigned int flags = default_section_type_flags (decl, name, reloc);
/* Align to at least UNIT size. */
- if (flags & SECTION_CODE)
+ if (flags & SECTION_CODE || !decl)
align = MIN_UNITS_PER_WORD;
else
/* Increase alignment of large objects if not already stricter. */
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 93b0b6c70be..22207bbf2b2 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -106,6 +106,7 @@
UNSPEC_SP_SET
UNSPEC_SP_TEST
UNSPEC_SYNC
+ UNSPEC_LWSYNC
UNSPEC_SYNC_OP
UNSPEC_ATOMIC
UNSPEC_CMPXCHG
@@ -138,7 +139,6 @@
UNSPECV_PROBE_STACK_RANGE ; probe range of stack addresses
UNSPECV_EH_RR ; eh_reg_restore
UNSPECV_ISYNC ; isync instruction
- UNSPECV_LWSYNC ; lwsync
])
diff --git a/gcc/config/rs6000/sync.md b/gcc/config/rs6000/sync.md
index c3fbd9ee028..38bd8bac354 100644
--- a/gcc/config/rs6000/sync.md
+++ b/gcc/config/rs6000/sync.md
@@ -28,12 +28,32 @@
(define_code_attr fetchop_pred
[(plus "add_operand") (minus "gpc_reg_operand")
(ior "logical_operand") (xor "logical_operand") (and "and_operand")])
-(define_code_attr fetchopsi_constr
- [(plus "rIL") (minus "r") (ior "rKL") (xor "rKL") (and "rTKL")])
-(define_code_attr fetchopdi_constr
- [(plus "rIL") (minus "r") (ior "rKJF") (xor "rKJF") (and "rSTKJ")])
-(define_expand "memory_barrier"
+(define_expand "mem_thread_fence"
+ [(match_operand:SI 0 "const_int_operand" "")] ;; model
+ ""
+{
+ enum memmodel model = (enum memmodel) INTVAL (operands[0]);
+ switch (model)
+ {
+ case MEMMODEL_RELAXED:
+ break;
+ case MEMMODEL_CONSUME:
+ case MEMMODEL_ACQUIRE:
+ case MEMMODEL_RELEASE:
+ case MEMMODEL_ACQ_REL:
+ emit_insn (gen_lwsync ());
+ break;
+ case MEMMODEL_SEQ_CST:
+ emit_insn (gen_hwsync ());
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ DONE;
+})
+
+(define_expand "hwsync"
[(set (match_dup 0)
(unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
""
@@ -42,582 +62,224 @@
MEM_VOLATILE_P (operands[0]) = 1;
})
-(define_insn "*sync_internal"
+(define_insn "*hwsync"
[(set (match_operand:BLK 0 "" "")
(unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
""
"{dcs|sync}"
[(set_attr "type" "sync")])
-(define_insn "load_locked_<mode>"
- [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
- (unspec_volatile:GPR
- [(match_operand:GPR 1 "memory_operand" "Z")] UNSPECV_LL))]
- "TARGET_POWERPC"
- "<larx> %0,%y1"
- [(set_attr "type" "load_l")])
-
-(define_insn "store_conditional_<mode>"
- [(set (match_operand:CC 0 "cc_reg_operand" "=x")
- (unspec_volatile:CC [(const_int 0)] UNSPECV_SC))
- (set (match_operand:GPR 1 "memory_operand" "=Z")
- (match_operand:GPR 2 "gpc_reg_operand" "r"))]
- "TARGET_POWERPC"
- "<stcx> %2,%y1"
- [(set_attr "type" "store_c")])
-
-(define_insn_and_split "sync_compare_and_swap<mode>"
- [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
- (match_operand:GPR 1 "memory_operand" "+Z"))
- (set (match_dup 1)
- (unspec:GPR
- [(match_operand:GPR 2 "reg_or_short_operand" "rI")
- (match_operand:GPR 3 "gpc_reg_operand" "r")]
- UNSPEC_CMPXCHG))
- (clobber (match_scratch:GPR 4 "=&r"))
- (clobber (match_scratch:CC 5 "=&x"))]
- "TARGET_POWERPC"
- "#"
- "&& reload_completed"
- [(const_int 0)]
+(define_expand "lwsync"
+ [(set (match_dup 0)
+ (unspec:BLK [(match_dup 0)] UNSPEC_LWSYNC))]
+ ""
{
- rs6000_split_compare_and_swap (operands[0], operands[1], operands[2],
- operands[3], operands[4]);
- DONE;
+ operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+ MEM_VOLATILE_P (operands[0]) = 1;
})
-(define_expand "sync_compare_and_swaphi"
- [(match_operand:HI 0 "gpc_reg_operand" "")
- (match_operand:HI 1 "memory_operand" "")
- (match_operand:HI 2 "gpc_reg_operand" "")
- (match_operand:HI 3 "gpc_reg_operand" "")]
- "TARGET_POWERPC"
+(define_insn "*lwsync"
+ [(set (match_operand:BLK 0 "" "")
+ (unspec:BLK [(match_dup 0)] UNSPEC_LWSYNC))]
+ ""
{
- rs6000_expand_compare_and_swapqhi (operands[0], operands[1],
- operands[2], operands[3]);
- DONE;
-})
+ /* Some AIX assemblers don't accept lwsync, so we use a .long. */
+ if (TARGET_NO_LWSYNC)
+ return "sync";
+ else if (TARGET_LWSYNC_INSTRUCTION)
+ return "lwsync";
+ else
+ return ".long 0x7c2004ac";
+}
+ [(set_attr "type" "sync")])
-(define_expand "sync_compare_and_swapqi"
- [(match_operand:QI 0 "gpc_reg_operand" "")
- (match_operand:QI 1 "memory_operand" "")
- (match_operand:QI 2 "gpc_reg_operand" "")
- (match_operand:QI 3 "gpc_reg_operand" "")]
- "TARGET_POWERPC"
-{
- rs6000_expand_compare_and_swapqhi (operands[0], operands[1],
- operands[2], operands[3]);
- DONE;
-})
+(define_insn "isync"
+ [(unspec_volatile:BLK [(const_int 0)] UNSPECV_ISYNC)]
+ ""
+ "{ics|isync}"
+ [(set_attr "type" "isync")])
-(define_insn_and_split "sync_compare_and_swapqhi_internal"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
- (match_operand:SI 4 "memory_operand" "+Z"))
- (set (match_dup 4)
- (unspec:SI
- [(match_operand:SI 1 "gpc_reg_operand" "r")
- (match_operand:SI 2 "gpc_reg_operand" "r")
- (match_operand:SI 3 "gpc_reg_operand" "r")]
- UNSPEC_CMPXCHG))
- (clobber (match_scratch:SI 5 "=&r"))
- (clobber (match_scratch:CC 6 "=&x"))]
- "TARGET_POWERPC"
- "#"
- "&& reload_completed"
- [(const_int 0)]
+;; The control dependency used for load dependency described
+;; in B.2.3 of the Power ISA 2.06B.
+(define_insn "loadsync"
+ [(unspec_volatile:BLK [(match_operand 0 "register_operand" "r")]
+ UNSPECV_ISYNC)
+ (clobber (match_scratch:CC 1 "=y"))]
+ ""
+ "cmpw %1,%0,%0\;bne- %1,$+4\;isync"
+ [(set_attr "type" "isync")
+ (set_attr "length" "12")])
+
+(define_expand "atomic_load<mode>"
+ [(set (match_operand:INT 0 "register_operand" "") ;; output
+ (match_operand:INT 1 "memory_operand" "")) ;; memory
+ (use (match_operand:SI 2 "const_int_operand" ""))] ;; model
+ ""
{
- rs6000_split_compare_and_swapqhi (operands[0], operands[1],
- operands[2], operands[3], operands[4],
- operands[5]);
- DONE;
-})
+ enum memmodel model = (enum memmodel) INTVAL (operands[2]);
-(define_insn_and_split "sync_lock_test_and_set<mode>"
- [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
- (match_operand:GPR 1 "memory_operand" "+Z"))
- (set (match_dup 1)
- (unspec:GPR
- [(match_operand:GPR 2 "reg_or_short_operand" "rL")]
- UNSPEC_XCHG))
- (clobber (match_scratch:GPR 3 "=&r"))
- (clobber (match_scratch:CC 4 "=&x"))]
- "TARGET_POWERPC"
- "#"
- "&& reload_completed"
- [(const_int 0)]
-{
- rs6000_split_lock_test_and_set (operands[0], operands[1], operands[2],
- operands[3]);
- DONE;
-})
+ if (model == MEMMODEL_SEQ_CST)
+ emit_insn (gen_hwsync ());
-(define_expand "sync_<fetchop_name><mode>"
- [(parallel [(set (match_operand:INT1 0 "memory_operand" "")
- (unspec:INT1
- [(FETCHOP:INT1 (match_dup 0)
- (match_operand:INT1 1 "<fetchop_pred>" ""))]
- UNSPEC_ATOMIC))
- (clobber (scratch:INT1))
- (clobber (scratch:CC))])]
- "TARGET_POWERPC"
- "
-{
- if (<MODE>mode != SImode && <MODE>mode != DImode)
+ emit_move_insn (operands[0], operands[1]);
+
+ switch (model)
{
- if (PPC405_ERRATUM77)
- FAIL;
- rs6000_emit_sync (<CODE>, <MODE>mode, operands[0], operands[1],
- NULL_RTX, NULL_RTX, true);
- DONE;
+ case MEMMODEL_RELAXED:
+ break;
+ case MEMMODEL_CONSUME:
+ case MEMMODEL_ACQUIRE:
+ case MEMMODEL_SEQ_CST:
+ emit_insn (gen_loadsync (operands[0]));
+ break;
+ default:
+ gcc_unreachable ();
}
-}")
-
-(define_insn_and_split "*sync_<fetchop_name>si_internal"
- [(set (match_operand:SI 0 "memory_operand" "+Z")
- (unspec:SI
- [(FETCHOP:SI (match_dup 0)
- (match_operand:SI 1 "<fetchop_pred>" "<fetchopsi_constr>"))]
- UNSPEC_ATOMIC))
- (clobber (match_scratch:SI 2 "=&b"))
- (clobber (match_scratch:CC 3 "=&x"))]
- "TARGET_POWERPC"
- "#"
- "&& reload_completed"
- [(const_int 0)]
-{
- rs6000_split_atomic_op (<CODE>, operands[0], operands[1],
- NULL_RTX, NULL_RTX, operands[2]);
DONE;
})
-(define_insn_and_split "*sync_<fetchop_name>di_internal"
- [(set (match_operand:DI 0 "memory_operand" "+Z")
- (unspec:DI
- [(FETCHOP:DI (match_dup 0)
- (match_operand:DI 1 "<fetchop_pred>" "<fetchopdi_constr>"))]
- UNSPEC_ATOMIC))
- (clobber (match_scratch:DI 2 "=&b"))
- (clobber (match_scratch:CC 3 "=&x"))]
- "TARGET_POWERPC"
- "#"
- "&& reload_completed"
- [(const_int 0)]
+(define_expand "atomic_store<mode>"
+ [(set (match_operand:INT 0 "memory_operand" "") ;; memory
+ (match_operand:INT 1 "register_operand" "")) ;; input
+ (use (match_operand:SI 2 "const_int_operand" ""))] ;; model
+ ""
{
- rs6000_split_atomic_op (<CODE>, operands[0], operands[1],
- NULL_RTX, NULL_RTX, operands[2]);
+ enum memmodel model = (enum memmodel) INTVAL (operands[2]);
+ switch (model)
+ {
+ case MEMMODEL_RELAXED:
+ break;
+ case MEMMODEL_RELEASE:
+ emit_insn (gen_lwsync ());
+ break;
+ case MEMMODEL_SEQ_CST:
+ emit_insn (gen_hwsync ());
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ emit_move_insn (operands[0], operands[1]);
DONE;
})
-(define_expand "sync_nand<mode>"
- [(parallel [(set (match_operand:INT1 0 "memory_operand" "")
- (unspec:INT1
- [(ior:INT1 (not:INT1 (match_dup 0))
- (not:INT1 (match_operand:INT1 1 "gpc_reg_operand" "")))]
- UNSPEC_ATOMIC))
- (clobber (scratch:INT1))
- (clobber (scratch:CC))])]
- "TARGET_POWERPC"
- "
-{
- if (<MODE>mode != SImode && <MODE>mode != DImode)
- {
- FAIL;
- if (PPC405_ERRATUM77)
- FAIL;
- rs6000_emit_sync (NOT, <MODE>mode, operands[0], operands[1],
- NULL_RTX, NULL_RTX, true);
- DONE;
- }
-}")
+;; ??? Power ISA 2.06B says that there *is* a load-{byte,half}-and-reserve
+;; opcode that is "phased-in". Not implemented as of Power7, so not yet used,
+;; but let's prepare the macros anyway.
+
+(define_mode_iterator ATOMIC [SI (DI "TARGET_64BIT")])
-(define_insn_and_split "*sync_nand<mode>_internal"
- [(set (match_operand:GPR 0 "memory_operand" "+Z")
- (unspec:GPR
- [(ior:GPR (not:GPR (match_dup 0))
- (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
- UNSPEC_ATOMIC))
- (clobber (match_scratch:GPR 2 "=&r"))
- (clobber (match_scratch:CC 3 "=&x"))]
+(define_insn "load_locked<mode>"
+ [(set (match_operand:ATOMIC 0 "gpc_reg_operand" "=r")
+ (unspec_volatile:ATOMIC
+ [(match_operand:ATOMIC 1 "memory_operand" "Z")] UNSPECV_LL))]
"TARGET_POWERPC"
- "#"
- "&& reload_completed"
- [(const_int 0)]
-{
- rs6000_split_atomic_op (NOT, operands[0], operands[1],
- NULL_RTX, NULL_RTX, operands[2]);
- DONE;
-})
+ "<larx> %0,%y1"
+ [(set_attr "type" "load_l")])
-(define_expand "sync_old_<fetchop_name><mode>"
- [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
- (match_operand:INT1 1 "memory_operand" ""))
- (set (match_dup 1)
- (unspec:INT1
- [(FETCHOP:INT1 (match_dup 1)
- (match_operand:INT1 2 "<fetchop_pred>" ""))]
- UNSPEC_ATOMIC))
- (clobber (scratch:INT1))
- (clobber (scratch:CC))])]
+(define_insn "store_conditional<mode>"
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+ (unspec_volatile:CC [(const_int 0)] UNSPECV_SC))
+ (set (match_operand:ATOMIC 1 "memory_operand" "=Z")
+ (match_operand:ATOMIC 2 "gpc_reg_operand" "r"))]
"TARGET_POWERPC"
- "
-{
- if (<MODE>mode != SImode && <MODE>mode != DImode)
- {
- if (PPC405_ERRATUM77)
- FAIL;
- rs6000_emit_sync (<CODE>, <MODE>mode, operands[1], operands[2],
- operands[0], NULL_RTX, true);
- DONE;
- }
-}")
+ "<stcx> %2,%y1"
+ [(set_attr "type" "store_c")])
-(define_insn_and_split "*sync_old_<fetchop_name>si_internal"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
- (match_operand:SI 1 "memory_operand" "+Z"))
- (set (match_dup 1)
- (unspec:SI
- [(FETCHOP:SI (match_dup 1)
- (match_operand:SI 2 "<fetchop_pred>" "<fetchopsi_constr>"))]
- UNSPEC_ATOMIC))
- (clobber (match_scratch:SI 3 "=&b"))
- (clobber (match_scratch:CC 4 "=&x"))]
+(define_expand "atomic_compare_and_swap<mode>"
+ [(match_operand:SI 0 "gpc_reg_operand" "") ;; bool out
+ (match_operand:INT1 1 "gpc_reg_operand" "") ;; val out
+ (match_operand:INT1 2 "memory_operand" "") ;; memory
+ (match_operand:INT1 3 "reg_or_short_operand" "") ;; expected
+ (match_operand:INT1 4 "gpc_reg_operand" "") ;; desired
+ (match_operand:SI 5 "const_int_operand" "") ;; is_weak
+ (match_operand:SI 6 "const_int_operand" "") ;; model succ
+ (match_operand:SI 7 "const_int_operand" "")] ;; model fail
"TARGET_POWERPC"
- "#"
- "&& reload_completed"
- [(const_int 0)]
{
- rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
- operands[0], NULL_RTX, operands[3]);
+ rs6000_expand_atomic_compare_and_swap (operands);
DONE;
})
-(define_insn_and_split "*sync_old_<fetchop_name>di_internal"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
- (match_operand:DI 1 "memory_operand" "+Z"))
- (set (match_dup 1)
- (unspec:DI
- [(FETCHOP:DI (match_dup 1)
- (match_operand:DI 2 "<fetchop_pred>" "<fetchopdi_constr>"))]
- UNSPEC_ATOMIC))
- (clobber (match_scratch:DI 3 "=&b"))
- (clobber (match_scratch:CC 4 "=&x"))]
+(define_expand "atomic_exchange<mode>"
+ [(match_operand:INT1 0 "gpc_reg_operand" "") ;; output
+ (match_operand:INT1 1 "memory_operand" "") ;; memory
+ (match_operand:INT1 2 "gpc_reg_operand" "") ;; input
+ (match_operand:SI 3 "const_int_operand" "")] ;; model
"TARGET_POWERPC"
- "#"
- "&& reload_completed"
- [(const_int 0)]
{
- rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
- operands[0], NULL_RTX, operands[3]);
+ rs6000_expand_atomic_exchange (operands);
DONE;
})
-(define_expand "sync_old_nand<mode>"
- [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
- (match_operand:INT1 1 "memory_operand" ""))
- (set (match_dup 1)
- (unspec:INT1
- [(ior:INT1 (not:INT1 (match_dup 1))
- (not:INT1 (match_operand:INT1 2 "gpc_reg_operand" "")))]
- UNSPEC_ATOMIC))
- (clobber (scratch:INT1))
- (clobber (scratch:CC))])]
- "TARGET_POWERPC"
- "
-{
- if (<MODE>mode != SImode && <MODE>mode != DImode)
- {
- FAIL;
- if (PPC405_ERRATUM77)
- FAIL;
- rs6000_emit_sync (NOT, <MODE>mode, operands[1], operands[2],
- operands[0], NULL_RTX, true);
- DONE;
- }
-}")
-
-(define_insn_and_split "*sync_old_nand<mode>_internal"
- [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
- (match_operand:GPR 1 "memory_operand" "+Z"))
- (set (match_dup 1)
- (unspec:GPR
- [(ior:GPR (not:GPR (match_dup 1))
- (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r")))]
- UNSPEC_ATOMIC))
- (clobber (match_scratch:GPR 3 "=&r"))
- (clobber (match_scratch:CC 4 "=&x"))]
+(define_expand "atomic_<fetchop_name><mode>"
+ [(match_operand:INT1 0 "memory_operand" "") ;; memory
+ (FETCHOP:INT1 (match_dup 0)
+ (match_operand:INT1 1 "<fetchop_pred>" "")) ;; operand
+ (match_operand:SI 2 "const_int_operand" "")] ;; model
"TARGET_POWERPC"
- "#"
- "&& reload_completed"
- [(const_int 0)]
{
- rs6000_split_atomic_op (NOT, operands[1], operands[2],
- operands[0], NULL_RTX, operands[3]);
+ rs6000_expand_atomic_op (<CODE>, operands[0], operands[1],
+ NULL_RTX, NULL_RTX, operands[2]);
DONE;
})
-(define_expand "sync_new_<fetchop_name><mode>"
- [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
- (FETCHOP:INT1
- (match_operand:INT1 1 "memory_operand" "")
- (match_operand:INT1 2 "<fetchop_pred>" "")))
- (set (match_dup 1)
- (unspec:INT1
- [(FETCHOP:INT1 (match_dup 1) (match_dup 2))]
- UNSPEC_ATOMIC))
- (clobber (scratch:INT1))
- (clobber (scratch:CC))])]
+(define_expand "atomic_nand<mode>"
+ [(match_operand:INT1 0 "memory_operand" "") ;; memory
+ (match_operand:INT1 1 "gpc_reg_operand" "") ;; operand
+ (match_operand:SI 2 "const_int_operand" "")] ;; model
"TARGET_POWERPC"
- "
{
- if (<MODE>mode != SImode && <MODE>mode != DImode)
- {
- if (PPC405_ERRATUM77)
- FAIL;
- rs6000_emit_sync (<CODE>, <MODE>mode, operands[1], operands[2],
- NULL_RTX, operands[0], true);
- DONE;
- }
-}")
-
-(define_insn_and_split "*sync_new_<fetchop_name>si_internal"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
- (FETCHOP:SI
- (match_operand:SI 1 "memory_operand" "+Z")
- (match_operand:SI 2 "<fetchop_pred>" "<fetchopsi_constr>")))
- (set (match_dup 1)
- (unspec:SI
- [(FETCHOP:SI (match_dup 1) (match_dup 2))]
- UNSPEC_ATOMIC))
- (clobber (match_scratch:SI 3 "=&b"))
- (clobber (match_scratch:CC 4 "=&x"))]
- "TARGET_POWERPC"
- "#"
- "&& reload_completed"
- [(const_int 0)]
-{
- rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
- NULL_RTX, operands[0], operands[3]);
+ rs6000_expand_atomic_op (NOT, operands[0], operands[1],
+ NULL_RTX, NULL_RTX, operands[2]);
DONE;
})
-(define_insn_and_split "*sync_new_<fetchop_name>di_internal"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
- (FETCHOP:DI
- (match_operand:DI 1 "memory_operand" "+Z")
- (match_operand:DI 2 "<fetchop_pred>" "<fetchopdi_constr>")))
- (set (match_dup 1)
- (unspec:DI
- [(FETCHOP:DI (match_dup 1) (match_dup 2))]
- UNSPEC_ATOMIC))
- (clobber (match_scratch:DI 3 "=&b"))
- (clobber (match_scratch:CC 4 "=&x"))]
+(define_expand "atomic_fetch_<fetchop_name><mode>"
+ [(match_operand:INT1 0 "gpc_reg_operand" "") ;; output
+ (match_operand:INT1 1 "memory_operand" "") ;; memory
+ (FETCHOP:INT1 (match_dup 1)
+ (match_operand:INT1 2 "<fetchop_pred>" "")) ;; operand
+ (match_operand:SI 3 "const_int_operand" "")] ;; model
"TARGET_POWERPC"
- "#"
- "&& reload_completed"
- [(const_int 0)]
-{
- rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
- NULL_RTX, operands[0], operands[3]);
+{
+ rs6000_expand_atomic_op (<CODE>, operands[1], operands[2],
+ operands[0], NULL_RTX, operands[3]);
DONE;
})
-(define_expand "sync_new_nand<mode>"
- [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
- (ior:INT1
- (not:INT1 (match_operand:INT1 1 "memory_operand" ""))
- (not:INT1 (match_operand:INT1 2 "gpc_reg_operand" ""))))
- (set (match_dup 1)
- (unspec:INT1
- [(ior:INT1 (not:INT1 (match_dup 1))
- (not:INT1 (match_dup 2)))]
- UNSPEC_ATOMIC))
- (clobber (scratch:INT1))
- (clobber (scratch:CC))])]
+(define_expand "atomic_fetch_nand<mode>"
+ [(match_operand:INT1 0 "gpc_reg_operand" "") ;; output
+ (match_operand:INT1 1 "memory_operand" "") ;; memory
+ (match_operand:INT1 2 "gpc_reg_operand" "") ;; operand
+ (match_operand:SI 3 "const_int_operand" "")] ;; model
"TARGET_POWERPC"
- "
{
- if (<MODE>mode != SImode && <MODE>mode != DImode)
- {
- FAIL;
- if (PPC405_ERRATUM77)
- FAIL;
- rs6000_emit_sync (NOT, <MODE>mode, operands[1], operands[2],
- NULL_RTX, operands[0], true);
- DONE;
- }
-}")
+ rs6000_expand_atomic_op (NOT, operands[1], operands[2],
+ operands[0], NULL_RTX, operands[3]);
+ DONE;
+})
-(define_insn_and_split "*sync_new_nand<mode>_internal"
- [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
- (ior:GPR
- (not:GPR (match_operand:GPR 1 "memory_operand" "+Z"))
- (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r"))))
- (set (match_dup 1)
- (unspec:GPR
- [(ior:GPR (not:GPR (match_dup 1)) (not:GPR (match_dup 2)))]
- UNSPEC_ATOMIC))
- (clobber (match_scratch:GPR 3 "=&r"))
- (clobber (match_scratch:CC 4 "=&x"))]
+(define_expand "atomic_<fetchop_name>_fetch<mode>"
+ [(match_operand:INT1 0 "gpc_reg_operand" "") ;; output
+ (match_operand:INT1 1 "memory_operand" "") ;; memory
+ (FETCHOP:INT1 (match_dup 1)
+ (match_operand:INT1 2 "<fetchop_pred>" "")) ;; operand
+ (match_operand:SI 3 "const_int_operand" "")] ;; model
"TARGET_POWERPC"
- "#"
- "&& reload_completed"
- [(const_int 0)]
{
- rs6000_split_atomic_op (NOT, operands[1], operands[2],
- NULL_RTX, operands[0], operands[3]);
+ rs6000_expand_atomic_op (<CODE>, operands[1], operands[2],
+ NULL_RTX, operands[0], operands[3]);
DONE;
})
-; and<mode> without cr0 clobber to avoid generation of additional clobber
-; in atomic splitters causing internal consistency failure.
-; cr0 already clobbered by larx/stcx.
-(define_insn "*atomic_andsi"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
- (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r")
- (match_operand:SI 2 "and_operand" "?r,T,K,L")]
- UNSPEC_AND))]
- ""
- "@
- and %0,%1,%2
- {rlinm|rlwinm} %0,%1,0,%m2,%M2
- {andil.|andi.} %0,%1,%b2
- {andiu.|andis.} %0,%1,%u2"
- [(set_attr "type" "*,*,compare,compare")])
-
-(define_insn "*atomic_anddi"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r")
- (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r")
- (match_operand:DI 2 "and_operand" "?r,S,T,K,J")]
- UNSPEC_AND))]
- "TARGET_POWERPC64"
- "@
- and %0,%1,%2
- rldic%B2 %0,%1,0,%S2
- rlwinm %0,%1,0,%m2,%M2
- andi. %0,%1,%b2
- andis. %0,%1,%u2"
- [(set_attr "type" "*,*,*,compare,compare")
- (set_attr "length" "4,4,4,4,4")])
-
-; the sync_*_internal patterns all have these operands:
-; 0 - memory location
-; 1 - operand
-; 2 - value in memory after operation
-; 3 - value in memory immediately before operation
-
-(define_insn "*sync_addshort_internal"
- [(set (match_operand:SI 2 "gpc_reg_operand" "=&r")
- (ior:SI (and:SI (plus:SI (match_operand:SI 0 "memory_operand" "+Z")
- (match_operand:SI 1 "add_operand" "rI"))
- (match_operand:SI 4 "gpc_reg_operand" "r"))
- (and:SI (not:SI (match_dup 4)) (match_dup 0))))
- (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
- (set (match_dup 0)
- (unspec:SI [(ior:SI (and:SI (plus:SI (match_dup 0) (match_dup 1))
- (match_dup 4))
- (and:SI (not:SI (match_dup 4)) (match_dup 0)))]
- UNSPEC_SYNC_OP))
- (clobber (match_scratch:CC 5 "=&x"))
- (clobber (match_scratch:SI 6 "=&r"))]
- "TARGET_POWERPC && !PPC405_ERRATUM77"
- "lwarx %3,%y0\n\tadd%I1 %2,%3,%1\n\tandc %6,%3,%4\n\tand %2,%2,%4\n\tor %2,%2,%6\n\tstwcx. %2,%y0\n\tbne- $-24"
- [(set_attr "length" "28")])
-
-(define_insn "*sync_subshort_internal"
- [(set (match_operand:SI 2 "gpc_reg_operand" "=&r")
- (ior:SI (and:SI (minus:SI (match_operand:SI 0 "memory_operand" "+Z")
- (match_operand:SI 1 "add_operand" "rI"))
- (match_operand:SI 4 "gpc_reg_operand" "r"))
- (and:SI (not:SI (match_dup 4)) (match_dup 0))))
- (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
- (set (match_dup 0)
- (unspec:SI [(ior:SI (and:SI (minus:SI (match_dup 0) (match_dup 1))
- (match_dup 4))
- (and:SI (not:SI (match_dup 4)) (match_dup 0)))]
- UNSPEC_SYNC_OP))
- (clobber (match_scratch:CC 5 "=&x"))
- (clobber (match_scratch:SI 6 "=&r"))]
- "TARGET_POWERPC && !PPC405_ERRATUM77"
- "lwarx %3,%y0\n\tsubf %2,%1,%3\n\tandc %6,%3,%4\n\tand %2,%2,%4\n\tor %2,%2,%6\n\tstwcx. %2,%y0\n\tbne- $-24"
- [(set_attr "length" "28")])
-
-(define_insn "*sync_andsi_internal"
- [(set (match_operand:SI 2 "gpc_reg_operand" "=&r,&r,&r,&r")
- (and:SI (match_operand:SI 0 "memory_operand" "+Z,Z,Z,Z")
- (match_operand:SI 1 "and_operand" "r,T,K,L")))
- (set (match_operand:SI 3 "gpc_reg_operand" "=&b,&b,&b,&b") (match_dup 0))
- (set (match_dup 0)
- (unspec:SI [(and:SI (match_dup 0) (match_dup 1))]
- UNSPEC_SYNC_OP))
- (clobber (match_scratch:CC 4 "=&x,&x,&x,&x"))]
- "TARGET_POWERPC && !PPC405_ERRATUM77"
- "@
- lwarx %3,%y0\n\tand %2,%3,%1\n\tstwcx. %2,%y0\n\tbne- $-12
- lwarx %3,%y0\n\trlwinm %2,%3,0,%m1,%M1\n\tstwcx. %2,%y0\n\tbne- $-12
- lwarx %3,%y0\n\tandi. %2,%3,%b1\n\tstwcx. %2,%y0\n\tbne- $-12
- lwarx %3,%y0\n\tandis. %2,%3,%u1\n\tstwcx. %2,%y0\n\tbne- $-12"
- [(set_attr "length" "16,16,16,16")])
-
-(define_insn "*sync_boolsi_internal"
- [(set (match_operand:SI 2 "gpc_reg_operand" "=&r,&r,&r")
- (match_operator:SI 4 "boolean_or_operator"
- [(match_operand:SI 0 "memory_operand" "+Z,Z,Z")
- (match_operand:SI 1 "logical_operand" "r,K,L")]))
- (set (match_operand:SI 3 "gpc_reg_operand" "=&b,&b,&b") (match_dup 0))
- (set (match_dup 0) (unspec:SI [(match_dup 4)] UNSPEC_SYNC_OP))
- (clobber (match_scratch:CC 5 "=&x,&x,&x"))]
- "TARGET_POWERPC && !PPC405_ERRATUM77"
- "@
- lwarx %3,%y0\n\t%q4 %2,%3,%1\n\tstwcx. %2,%y0\n\tbne- $-12
- lwarx %3,%y0\n\t%q4i %2,%3,%b1\n\tstwcx. %2,%y0\n\tbne- $-12
- lwarx %3,%y0\n\t%q4is %2,%3,%u1\n\tstwcx. %2,%y0\n\tbne- $-12"
- [(set_attr "length" "16,16,16")])
-
-; This pattern could also take immediate values of operand 1,
-; since the non-NOT version of the operator is used; but this is not
-; very useful, since in practice operand 1 is a full 32-bit value.
-; Likewise, operand 5 is in practice either <= 2^16 or it is a register.
-(define_insn "*sync_boolcshort_internal"
- [(set (match_operand:SI 2 "gpc_reg_operand" "=&r")
- (match_operator:SI 4 "boolean_or_operator"
- [(xor:SI (not:SI (match_operand:SI 0 "memory_operand" "+Z"))
- (not:SI (match_operand:SI 5 "logical_operand" "rK")))
- (match_operand:SI 1 "gpc_reg_operand" "r")]))
- (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
- (set (match_dup 0) (unspec:SI [(match_dup 4)] UNSPEC_SYNC_OP))
- (clobber (match_scratch:CC 6 "=&x"))]
- "TARGET_POWERPC && !PPC405_ERRATUM77"
- "lwarx %3,%y0\n\txor%I2 %2,%3,%5\n\t%q4 %2,%2,%1\n\tstwcx. %2,%y0\n\tbne- $-16"
- [(set_attr "length" "20")])
-
-(define_insn "isync"
- [(set (mem:BLK (match_scratch 0 "X"))
- (unspec_volatile:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPECV_ISYNC))]
- ""
- "{ics|isync}"
- [(set_attr "type" "isync")])
-
-(define_expand "sync_lock_release<mode>"
- [(set (match_operand:INT 0 "memory_operand")
- (match_operand:INT 1 "any_operand"))]
- ""
- "
+(define_expand "atomic_nand_fetch<mode>"
+ [(match_operand:INT1 0 "gpc_reg_operand" "") ;; output
+ (match_operand:INT1 1 "memory_operand" "") ;; memory
+ (match_operand:INT1 2 "gpc_reg_operand" "") ;; operand
+ (match_operand:SI 3 "const_int_operand" "")] ;; model
+ "TARGET_POWERPC"
{
- emit_insn (gen_lwsync ());
- emit_move_insn (operands[0], operands[1]);
+ rs6000_expand_atomic_op (NOT, operands[1], operands[2],
+ NULL_RTX, operands[0], operands[3]);
DONE;
-}")
-
-; Some AIX assemblers don't accept lwsync, so we use a .long.
-(define_insn "lwsync"
- [(set (mem:BLK (match_scratch 0 "X"))
- (unspec_volatile:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPECV_LWSYNC))]
- ""
-{
- if (TARGET_NO_LWSYNC)
- return "sync";
- else
- return (TARGET_LWSYNC_INSTRUCTION) ? "lwsync" : ".long 0x7c2004ac";
-}
- [(set_attr "type" "sync")])
-
+})
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index ccf20b1bcaa..10fa5edbb66 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -109,6 +109,8 @@ 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);
+unsigned int sparc_regmode_natural_size (enum machine_mode);
+bool sparc_modes_tieable_p (enum machine_mode, enum machine_mode);
#endif /* RTX_CODE */
#endif /* __SPARC_PROTOS_H__ */
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 55759a03bd1..b315698bc94 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -11616,4 +11616,69 @@ sparc_expand_vcond (enum machine_mode mode, rtx *operands, int ccode, int fcode)
emit_insn (gen_rtx_SET (VOIDmode, operands[0], bshuf));
}
+/* On sparc, any mode which naturally allocates into the float
+ registers should return 4 here. */
+
+unsigned int
+sparc_regmode_natural_size (enum machine_mode mode)
+{
+ int size = UNITS_PER_WORD;
+
+ if (TARGET_ARCH64)
+ {
+ enum mode_class mclass = GET_MODE_CLASS (mode);
+
+ if (mclass == MODE_FLOAT || mclass == MODE_VECTOR_INT)
+ size = 4;
+ }
+
+ return size;
+}
+
+/* Return TRUE if it is a good idea to tie two pseudo registers
+ when one has mode MODE1 and one has mode MODE2.
+ If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+ for any hard reg, then this must be FALSE for correct output.
+
+ For V9 we have to deal with the fact that only the lower 32 floating
+ point registers are 32-bit addressable. */
+
+bool
+sparc_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
+{
+ enum mode_class mclass1, mclass2;
+ unsigned short size1, size2;
+
+ if (mode1 == mode2)
+ return true;
+
+ mclass1 = GET_MODE_CLASS (mode1);
+ mclass2 = GET_MODE_CLASS (mode2);
+ if (mclass1 != mclass2)
+ return false;
+
+ if (! TARGET_V9)
+ return true;
+
+ /* Classes are the same and we are V9 so we have to deal with upper
+ vs. lower floating point registers. If one of the modes is a
+ 4-byte mode, and the other is not, we have to mark them as not
+ tieable because only the lower 32 floating point register are
+ addressable 32-bits at a time.
+
+ We can't just test explicitly for SFmode, otherwise we won't
+ cover the vector mode cases properly. */
+
+ if (mclass1 != MODE_FLOAT && mclass1 != MODE_VECTOR_INT)
+ return true;
+
+ size1 = GET_MODE_SIZE (mode1);
+ size2 = GET_MODE_SIZE (mode2);
+ if ((size1 > 4 && size2 == 4)
+ || (size2 > 4 && size1 == 4))
+ return false;
+
+ return true;
+}
+
#include "gt-sparc.h"
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index e8707f50577..32f8c1074ae 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -716,8 +716,7 @@ extern enum cmodel sparc_cmodel;
/* Due to the ARCH64 discrepancy above we must override this next
macro too. */
-#define REGMODE_NATURAL_SIZE(MODE) \
- ((TARGET_ARCH64 && FLOAT_MODE_P (MODE)) ? 4 : UNITS_PER_WORD)
+#define REGMODE_NATURAL_SIZE(MODE) sparc_regmode_natural_size (MODE)
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
See sparc.c for how we initialize this. */
@@ -735,20 +734,7 @@ extern int sparc_mode_class[];
register window instruction in the prologue. */
#define HARD_REGNO_RENAME_OK(FROM, TO) ((FROM) != 1)
-/* Value is 1 if it is a good idea to tie two pseudo registers
- when one has mode MODE1 and one has mode MODE2.
- If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
- for any hard reg, then this must be 0 for correct output.
-
- For V9: SFmode can't be combined with other float modes, because they can't
- be allocated to the %d registers. Also, DFmode won't fit in odd %f
- registers, but SFmode will. */
-#define MODES_TIEABLE_P(MODE1, MODE2) \
- ((MODE1) == (MODE2) \
- || (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2) \
- && (! TARGET_V9 \
- || (GET_MODE_CLASS (MODE1) != MODE_FLOAT \
- || (MODE1 != SFmode && MODE2 != SFmode)))))
+#define MODES_TIEABLE_P(MODE1, MODE2) sparc_modes_tieable_p (MODE1, MODE2)
/* Specify the registers used for certain standard purposes.
The values of these macros are register numbers. */
diff --git a/gcc/config/vms/vms-c.c b/gcc/config/vms/vms-c.c
index eb4c63577a9..b3e0d955f19 100644
--- a/gcc/config/vms/vms-c.c
+++ b/gcc/config/vms/vms-c.c
@@ -227,6 +227,42 @@ vms_pragma_message (cpp_reader *pfile ATTRIBUTE_UNUSED)
#endif
}
+/* Handle '#pragma __extern_prefix' */
+
+static GTY(()) tree saved_extern_prefix;
+
+static void
+vms_pragma_extern_prefix (cpp_reader * ARG_UNUSED (dummy))
+{
+ enum cpp_ttype tok;
+ tree x;
+
+ tok = pragma_lex (&x);
+ if (tok == CPP_NAME)
+ {
+ const char *op = IDENTIFIER_POINTER (x);
+
+ if (!strcmp (op, "__save"))
+ saved_extern_prefix = pragma_extern_prefix;
+ else if (!strcmp (op, "__restore"))
+ pragma_extern_prefix = saved_extern_prefix;
+ else
+ warning (OPT_Wpragmas,
+ "malformed '#pragma __extern_prefix', ignoring");
+ return;
+ }
+ else if (tok != CPP_STRING)
+ {
+ warning (OPT_Wpragmas,
+ "malformed '#pragma __extern_prefix', ignoring");
+ }
+ else
+ {
+ /* Note that the length includes the null terminator. */
+ pragma_extern_prefix = (TREE_STRING_LENGTH (x) > 1 ? x : NULL);
+ }
+}
+
/* Add vms-specific pragma. */
void
@@ -245,4 +281,52 @@ vms_c_register_pragma (void)
c_register_pragma (NULL, "__extern_model", vms_pragma_extern_model);
c_register_pragma (NULL, "extern_model", vms_pragma_extern_model);
c_register_pragma (NULL, "__message", vms_pragma_message);
+ c_register_pragma (NULL, "__extern_prefix", vms_pragma_extern_prefix);
+}
+
+/* Standard modules list. */
+static const char * const vms_std_modules[] = { "rtldef", "starlet_c", NULL };
+
+/* Find include modules in the include path. */
+
+void
+vms_c_register_includes (const char *sysroot,
+ const char *iprefix ATTRIBUTE_UNUSED, int stdinc)
+{
+ static const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
+ struct cpp_dir *dir;
+
+ /* Add on standard include pathes. */
+ if (!stdinc)
+ return;
+
+ for (dir = get_added_cpp_dirs (SYSTEM); dir != NULL; dir = dir->next)
+ {
+ const char * const *lib;
+ for (lib = vms_std_modules; *lib != NULL; lib++)
+ {
+ char *path;
+ struct stat st;
+
+ if (sysroot != NULL)
+ path = concat (sysroot, dir->name, dir_separator_str, *lib, NULL);
+ else
+ path = concat (dir->name, dir_separator_str, *lib, NULL);
+
+ if (stat (path, &st) == 0 && S_ISDIR (st.st_mode))
+ {
+ cpp_dir *p;
+
+ p = XNEW (cpp_dir);
+ p->next = NULL;
+ p->name = path;
+ p->sysp = 1;
+ p->construct = 0;
+ p->user_supplied_p = 0;
+ add_cpp_dir_path (p, SYSTEM);
+ }
+ else
+ free (path);
+ }
+ }
}
diff --git a/gcc/config/vms/vms.h b/gcc/config/vms/vms.h
index 0da9d85a89c..62e8636cae4 100644
--- a/gcc/config/vms/vms.h
+++ b/gcc/config/vms/vms.h
@@ -34,6 +34,9 @@ along with GCC; see the file COPYING3. If not see
} \
} while (0)
+extern void vms_c_register_includes (const char *, const char *, int);
+#define TARGET_EXTRA_INCLUDES vms_c_register_includes
+
/* Tell compiler we want to support VMS pragmas */
#define REGISTER_TARGET_PRAGMAS() vms_c_register_pragma ()
diff --git a/gcc/configure b/gcc/configure
index d8654121837..2da771427d7 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -7597,17 +7597,7 @@ else
RANLIB="$ac_cv_prog_RANLIB"
fi
-case "${host}" in
-*-*-darwin*)
- # By default, the Darwin ranlib will not treat common symbols as
- # definitions when building the archive table of contents. Other
- # ranlibs do that; pass an option to the Darwin ranlib that makes
- # it behave similarly.
- ranlib_flags="-c"
- ;;
-*)
- ranlib_flags=""
-esac
+ranlib_flags=""
# Find a good install program. We prefer a C program (faster),
@@ -16322,7 +16312,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct=yes
hardcode_minus_L=yes
@@ -17235,7 +17225,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -17253,7 +17243,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
@@ -18087,7 +18077,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 18090 "configure"
+#line 18080 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -18193,7 +18183,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 18196 "configure"
+#line 18186 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -19119,7 +19109,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
esac
;;
- freebsd[12]*)
+ freebsd2.*)
# C++ shared libraries reported to be fairly broken before
# switch to ELF
ld_shlibs_CXX=no
@@ -20894,7 +20884,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -20912,7 +20902,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
diff --git a/gcc/configure.ac b/gcc/configure.ac
index af5b748b0f5..12492ff1fe5 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -847,17 +847,7 @@ esac
gcc_AC_PROG_LN_S
ACX_PROG_LN($LN_S)
AC_PROG_RANLIB
-case "${host}" in
-*-*-darwin*)
- # By default, the Darwin ranlib will not treat common symbols as
- # definitions when building the archive table of contents. Other
- # ranlibs do that; pass an option to the Darwin ranlib that makes
- # it behave similarly.
- ranlib_flags="-c"
- ;;
-*)
- ranlib_flags=""
-esac
+ranlib_flags=""
AC_SUBST(ranlib_flags)
gcc_AC_PROG_INSTALL
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 520652b1e71..65ceba22783 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -657,9 +657,8 @@ coverage_end_function (unsigned lineno_checksum, unsigned cfg_checksum)
}
/* Build a coverage variable of TYPE for function FN_DECL. If COUNTER
- >= 0 it is a counter array, and thus local. Otherwise it is the
- function structure and needs to be globalized. All cases must be
- in the same comdat group as FN_DECL. */
+ >= 0 it is a counter array, otherwise it is the function structure.
+ Propagate appropriate linkage and visibility from the function decl. */
static tree
build_var (tree fn_decl, tree type, int counter)
@@ -668,29 +667,29 @@ build_var (tree fn_decl, tree type, int counter)
tree fn_name = DECL_ASSEMBLER_NAME (fn_decl);
char *buf = (char *)alloca (IDENTIFIER_LENGTH (fn_name) + 10);
- if (counter >= 0)
- TREE_STATIC (var) = 1;
- else
- {
- TREE_PUBLIC (var) = TREE_PUBLIC (fn_decl);
- TREE_STATIC (var) = TREE_STATIC (fn_decl);
- }
- TREE_ADDRESSABLE (var) = 1;
- DECL_ALIGN (var) = TYPE_ALIGN (type);
-
if (counter < 0)
sprintf (buf, "__gcov__%s", IDENTIFIER_POINTER (fn_name));
else
sprintf (buf, "__gcov%u_%s", counter, IDENTIFIER_POINTER (fn_name));
DECL_NAME (var) = get_identifier (buf);
-
- /* Initialize assembler name so we can stream out. */
+ TREE_STATIC (var) = 1;
+ TREE_ADDRESSABLE (var) = 1;
+ DECL_ALIGN (var) = TYPE_ALIGN (type);
+ DECL_WEAK (var) = DECL_WEAK (fn_decl);
+ TREE_PUBLIC (var)
+ = TREE_PUBLIC (fn_decl) && (counter < 0 || DECL_WEAK (fn_decl));
+ if (DECL_ONE_ONLY (fn_decl))
+ make_decl_one_only (var, DECL_COMDAT_GROUP (fn_decl));
+
if (TREE_PUBLIC (var))
- DECL_ASSEMBLER_NAME (var);
+ {
+ DECL_VISIBILITY (var) = DECL_VISIBILITY (fn_decl);
+ DECL_VISIBILITY_SPECIFIED (var)
+ = DECL_VISIBILITY_SPECIFIED (fn_decl);
- DECL_WEAK (var) = TREE_PUBLIC (var) && DECL_WEAK (fn_decl);
- DECL_COMDAT (var) = DECL_COMDAT (fn_decl);
- DECL_COMDAT_GROUP (var) = DECL_COMDAT_GROUP (fn_decl);
+ /* Initialize assembler name so we can stream out. */
+ DECL_ASSEMBLER_NAME (var);
+ }
return var;
}
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a33332cc6a9..0772ee9715c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,165 @@
+2011-11-24 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51227
+ * pt.c (instantiate_class_template_1): If lambda_function (type)
+ is NULL_TREE do not instantiate_decl.
+
+2011-11-24 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51290
+ * class.c (build_base_path): For the null pointer check use
+ nullptr_node instead of integer_zero_node.
+
+2011-11-22 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/51145
+ * decl.c (check_elaborated_type_specifier): Gracefully handle
+ error_mark_node. Accept bound template template parameters.
+ Update diagnostics for alias template specializations. Update
+ comment.
+ * parser.c (cp_parser_elaborated_type_specifier): Use
+ check_elaborated_type_specifier for simple-template-ids as well.
+
+2011-11-22 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51265
+ * semantics.c (finish_decltype_type): Handle PTRMEM_CST.
+
+2011-11-22 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/51143
+ * parser.c (cp_parser_alias_declaration): Don't allow type
+ definition in templates.
+
+2011-11-22 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51196
+ * typeck.c (cp_build_binary_op, [case EQ_EXPR]): For targets having
+ TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta, do here
+ the -Wzero-as-null-pointer-constant warning for pmf == 0.
+
+2011-11-21 Torvald Riegel <triegel@redhat.com>
+
+ * pt.c (tsubst_copy_and_build): Handle TRANSACTION_EXPR.
+
+2011-11-21 Ed Smith-Rowland <3dw4rd@verizon.net>
+
+ PR c++/50958
+ * parser.c (lookup_literal_operator): New.
+ (cp_parser_userdef_char_literal): Use it.
+ (cp_parser_userdef_numeric_literal): Use it.
+ (cp_parser_userdef_string_literal): Use lookup_name.
+
+2011-11-20 Jason Merrill <jason@redhat.com>
+
+ * pt.c (tsubst_pack_expansion): Fix SFINAE.
+
+ PR c++/48322
+ * cp-tree.h (PACK_EXPANSION_EXTRA_ARGS): New.
+ * cp-tree.def (EXPR_PACK_EXPANSION): Add an operand for it.
+ * pt.c (tsubst_pack_expansion): Set and use it.
+ (iterative_hash_template_arg): Hash it.
+ (template_args_equal): Compare it.
+ (comp_template_args_with_info): Handle nulls.
+ * tree.c (cp_walk_subtrees): Walk it.
+ * typeck.c (structural_comptypes): Compare it.
+ * ptree.c (cxx_print_type): Print it.
+
+ * pt.c (type_unification_real): Set input_location
+ during default arg instantiation.
+
+2011-11-20 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51230
+ * pt.c (unify_inconsistency): Handle non-type parameters better.
+ * error.c (dump_expr): Handle TEMPLATE_TEMPLATE_PARM.
+
+2011-11-20 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/51194
+ * pt.c (lookup_template_class_1): Go out early if the type of the
+ template is error_mark_node.
+
+2011-11-19 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51216
+ * semantics.c (potential_constant_expression_1): Handle IF_STMT,
+ DO_STMT, FOR_STMT, and WHILE_STMT.
+
+2011-11-18 Fabien Chêne <fabien@gcc.gnu.org>
+
+ PR c++/51188
+ * search.c (lookup_field_1): Handle USING_DECLs for the storted
+ case.
+
+2011-11-18 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51150
+ * pt.c (tsubst_copy_and_build): Handle FIX_TRUNC_EXPR.
+
+2011-11-18 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/51191
+ * pt.c (primary_template_instantiation_p): Don't forget to
+ consider alias declarations.
+
+2011-11-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/51186
+ * decl.c (grokdeclarator): Improve C++98 trailing return diagnostic.
+
+ N3203
+ * class.c (add_implicitly_declared_members): Update move
+ conditions.
+
+ PR c++/51137
+ * class.c (build_base_path): Don't do calculation in templates.
+
+2011-11-15 Torvald Riegel <triegel@redhat.com>
+
+ * parser.c (cp_parser_transaction_expression): Require parentheses
+ when parsing transaction expressions.
+
+2011-11-14 Ed Smith-Rowland <3dw4rd@verizon.net>
+
+ PR c++/51107
+ * typeck.c (check_literal_operator_args): Add processing_specialization
+ to check for void template fn. Test for exact arity for non-template fn.
+
+2011-11-14 Fabien Chêne <fabien@gcc.gnu.org>
+
+ PR c++/6936
+ PR c++/25994
+ PR c++/26256
+ PR c++/30195
+ * search.c (lookup_field_1): Look through USING_DECL.
+ (lookup_field_r): Call lookup_fnfields_slot instead of
+ lookup_fnfields_1.
+ * semantics.c (finish_member_declaration): Remove the check that
+ prevents USING_DECLs from being verified by
+ pushdecl_class_level. Call add_method for using declarations that
+ designates functions if the using declaration is in a template
+ class. Set DECL_IGNORED_P on class-scope using declarations.
+ * typeck.c (build_class_member_access_expr): Handle USING_DECLs.
+ * class.c (check_field_decls): Keep using declarations.
+ (add_method): Remove two diagnostics about conflicting using
+ declarations.
+ * parser.c (cp_parser_nonclass_name): Handle USING_DECLs.
+ * decl.c (start_enum): Call xref_tag whenever possible.
+ * cp-tree.h (strip_using_decl): Declare, and reident the previous
+ function.
+ * name-lookup.c (strip_using_decl): New function.
+ (supplement_binding_1): Call strip_using_decl on decl and
+ bval. Perform most of the checks with USING_DECLs stripped. Also
+ check that the target decl and the target bval does not refer to
+ the same declaration. Allow pushing an enum multiple times in a
+ template class. Adjustment to diagnose using redeclarations. Call
+ diagnose_name_conflict.
+ (push_class_level_binding): Call strip_using_decl on decl and
+ bval. Perform most of the checks with USING_DECLs stripped. Return
+ true if both decl and bval refer to USING_DECLs and are dependent.
+ (diagnose_name_conflict): New function.
+
2011-11-12 Jason Merrill <jason@redhat.com>
PR c++/986
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index d2cf63c7d0f..3cb76de60aa 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -304,8 +304,13 @@ build_base_path (enum tree_code code,
virtual_access = (v_binfo && fixed_type_p <= 0);
/* Don't bother with the calculations inside sizeof; they'll ICE if the
- source type is incomplete and the pointer value doesn't matter. */
- if (cp_unevaluated_operand != 0)
+ source type is incomplete and the pointer value doesn't matter. In a
+ template (even in fold_non_dependent_expr), we don't have vtables set
+ up properly yet, and the value doesn't matter there either; we're just
+ interested in the result of overload resolution. */
+ if (cp_unevaluated_operand != 0
+ || (current_function_decl
+ && uses_template_parms (current_function_decl)))
{
expr = build_nop (ptr_target_type, expr);
if (!want_pointer)
@@ -333,7 +338,7 @@ build_base_path (enum tree_code code,
/* Now that we've saved expr, build the real null test. */
if (null_test)
{
- tree zero = cp_convert (TREE_TYPE (expr), integer_zero_node);
+ tree zero = cp_convert (TREE_TYPE (expr), nullptr_node);
null_test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
expr, zero);
}
@@ -359,11 +364,6 @@ build_base_path (enum tree_code code,
V_BINFO. That offset is an entry in D_BINFO's vtable. */
tree v_offset;
- /* In a constructor template, current_in_charge_parm isn't set,
- and we might end up here via fold_non_dependent_expr. */
- if (fixed_type_p < 0 && !(cfun && current_in_charge_parm))
- fixed_type_p = 0;
-
if (fixed_type_p < 0 && in_base_initializer)
{
/* In a base member initializer, we cannot rely on the
@@ -1058,11 +1058,6 @@ add_method (tree type, tree method, tree using_decl)
if (DECL_CONTEXT (fn) == type)
/* Defer to the local function. */
return false;
- if (DECL_CONTEXT (fn) == DECL_CONTEXT (method))
- error ("repeated using declaration %q+D", using_decl);
- else
- error ("using declaration %q+D conflicts with a previous using declaration",
- using_decl);
}
else
{
@@ -2726,6 +2721,13 @@ add_implicitly_declared_members (tree t,
int cant_have_const_cctor,
int cant_have_const_assignment)
{
+ bool move_ok = false;
+
+ if (cxx_dialect >= cxx0x && !CLASSTYPE_DESTRUCTORS (t)
+ && !TYPE_HAS_COPY_CTOR (t) && !TYPE_HAS_COPY_ASSIGN (t)
+ && !type_has_move_constructor (t) && !type_has_move_assign (t))
+ move_ok = true;
+
/* Destructor. */
if (!CLASSTYPE_DESTRUCTORS (t))
{
@@ -2763,7 +2765,7 @@ add_implicitly_declared_members (tree 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 && !type_has_move_constructor (t))
+ if (move_ok)
CLASSTYPE_LAZY_MOVE_CTOR (t) = 1;
}
@@ -2776,7 +2778,7 @@ add_implicitly_declared_members (tree 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 && !type_has_move_assign (t))
+ if (move_ok)
CLASSTYPE_LAZY_MOVE_ASSIGN (t) = 1;
}
@@ -3039,15 +3041,8 @@ check_field_decls (tree t, tree *access_decls,
if (TREE_CODE (x) == USING_DECL)
{
- /* Prune the access declaration from the list of fields. */
- *field = DECL_CHAIN (x);
-
/* Save the access declarations for our caller. */
*access_decls = tree_cons (NULL_TREE, x, *access_decls);
-
- /* Since we've reset *FIELD there's no reason to skip to the
- next field. */
- next = field;
continue;
}
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index 4eec9f97c7d..5fc5496ef9e 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -419,7 +419,7 @@ DEFTREECODE (TYPE_PACK_EXPANSION, "type_pack_expansion", tcc_type, 0)
EXPR_PACK_EXPANSION plays precisely the same role as TYPE_PACK_EXPANSION,
but will be used for expressions. */
-DEFTREECODE (EXPR_PACK_EXPANSION, "expr_pack_expansion", tcc_expression, 2)
+DEFTREECODE (EXPR_PACK_EXPANSION, "expr_pack_expansion", tcc_expression, 3)
/* Selects the Ith parameter out of an argument pack. This node will
be used when instantiating pack expansions; see
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b306976c62c..3f4f4081f38 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2813,7 +2813,14 @@ extern void decl_shadowed_for_var_insert (tree, tree);
#define PACK_EXPANSION_PARAMETER_PACKS(NODE) \
*(TREE_CODE (NODE) == EXPR_PACK_EXPANSION \
? &TREE_OPERAND (NODE, 1) \
- : &TREE_CHAIN (TYPE_PACK_EXPANSION_CHECK (NODE)))
+ : &TYPE_MINVAL (TYPE_PACK_EXPANSION_CHECK (NODE)))
+
+/* Any additional template args to be applied when substituting into
+ the pattern, set by tsubst_pack_expansion for partial instantiations. */
+#define PACK_EXPANSION_EXTRA_ARGS(NODE) \
+ *(TREE_CODE (NODE) == TYPE_PACK_EXPANSION \
+ ? &TYPE_MAXVAL (NODE) \
+ : &TREE_OPERAND ((NODE), 2))
/* Determine if this is an argument pack. */
#define ARGUMENT_PACK_P(NODE) \
@@ -5886,7 +5893,8 @@ extern void cxx_omp_finish_clause (tree);
extern bool cxx_omp_privatize_by_reference (const_tree);
/* in name-lookup.c */
-extern void suggest_alternatives_for (location_t, tree);
+extern void suggest_alternatives_for (location_t, tree);
+extern tree strip_using_decl (tree);
/* -- end of C++ */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 1c46adf99a1..84064326f4d 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -9126,12 +9126,12 @@ grokdeclarator (const cp_declarator *declarator,
if (!declarator->u.function.late_return_type)
{
error ("%qs function uses %<auto%> type specifier without"
- " late return type", name);
+ " trailing return type", name);
return error_mark_node;
}
else if (!is_auto (type))
{
- error ("%qs function with late return type has"
+ error ("%qs function with trailing return type has"
" %qT as its type rather than plain %<auto%>",
name, type);
return error_mark_node;
@@ -9139,8 +9139,14 @@ grokdeclarator (const cp_declarator *declarator,
}
else if (declarator->u.function.late_return_type)
{
- error ("%qs function with late return type not declared"
- " with %<auto%> type specifier", name);
+ if (cxx_dialect < cxx0x)
+ /* Not using maybe_warn_cpp0x because this should
+ always be an error. */
+ error ("trailing return type only available with "
+ "-std=c++11 or -std=gnu++11");
+ else
+ error ("%qs function with trailing return type not "
+ "declared with %<auto%> type specifier", name);
return error_mark_node;
}
}
@@ -11336,6 +11342,9 @@ check_elaborated_type_specifier (enum tag_types tag_code,
{
tree type;
+ if (decl == error_mark_node)
+ return error_mark_node;
+
/* In the case of:
struct S { struct S *p; };
@@ -11355,10 +11364,15 @@ check_elaborated_type_specifier (enum tag_types tag_code,
type, tag_name (tag_code));
return error_mark_node;
}
+ /* Accept bound template template parameters. */
+ else if (allow_template_p
+ && TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
+ ;
/* [dcl.type.elab]
- If the identifier resolves to a typedef-name or a template
- type-parameter, the elaborated-type-specifier is ill-formed.
+ If the identifier resolves to a typedef-name or the
+ simple-template-id resolves to an alias template
+ specialization, the elaborated-type-specifier is ill-formed.
In other words, the only legitimate declaration to use in the
elaborated type specifier is the implicit typedef created when
@@ -11367,8 +11381,13 @@ check_elaborated_type_specifier (enum tag_types tag_code,
&& !DECL_SELF_REFERENCE_P (decl)
&& tag_code != typename_type)
{
- error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
- error ("%q+D has a previous declaration here", decl);
+ if (alias_template_specialization_p (type))
+ error ("using alias template specialization %qT after %qs",
+ type, tag_name (tag_code));
+ else
+ error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
+ inform (DECL_SOURCE_LOCATION (decl),
+ "%qD has a previous declaration here", decl);
return error_mark_node;
}
else if (TREE_CODE (type) != RECORD_TYPE
@@ -11988,8 +12007,22 @@ start_enum (tree name, tree enumtype, tree underlying_type,
*is_new = true;
}
prevtype = enumtype;
- enumtype = cxx_make_type (ENUMERAL_TYPE);
- enumtype = pushtag (name, enumtype, /*tag_scope=*/ts_current);
+
+ /* Do not push the decl more than once, unless we need to
+ compare underlying types at instantiation time */
+ if (!enumtype
+ || (underlying_type
+ && dependent_type_p (underlying_type))
+ || (ENUM_UNDERLYING_TYPE (enumtype)
+ && dependent_type_p (ENUM_UNDERLYING_TYPE (enumtype))))
+ {
+ enumtype = cxx_make_type (ENUMERAL_TYPE);
+ enumtype = pushtag (name, enumtype, /*tag_scope=*/ts_current);
+ }
+ else
+ enumtype = xref_tag (enum_type, name, /*tag_scope=*/ts_current,
+ false);
+
if (enumtype == error_mark_node)
return error_mark_node;
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 602cb75236a..4940a783353 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -2406,6 +2406,7 @@ dump_expr (tree t, int flags)
break;
case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_TEMPLATE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
dump_type (t, flags);
break;
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 5c20e32a79f..7e9ad54706f 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -598,7 +598,9 @@ perform_member_init (tree member, tree init)
init = digest_init (type, init, tf_warning_or_error);
if (init == error_mark_node)
return;
- /* Use 'this' as the decl, as it has the lifetime we want. */
+ /* A FIELD_DECL doesn't really have a suitable lifetime, but
+ make_temporary_var_for_ref_to_temp will treat it as automatic and
+ set_up_extended_ref_temp wants to use the decl in a warning. */
init = extend_ref_init_temps (member, init, &cleanups);
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (type)))
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 044a97f7157..7f6b8cdcf29 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -53,6 +53,7 @@ static bool qualified_lookup_using_namespace (tree, tree,
static tree lookup_type_current_level (tree);
static tree push_using_directive (tree);
static tree lookup_extern_c_fun_in_all_ns (tree);
+static void diagnose_name_conflict (tree, tree);
/* The :: namespace. */
@@ -394,6 +395,16 @@ pop_binding (tree id, tree decl)
}
}
+/* Strip non dependent using declarations. */
+
+tree
+strip_using_decl (tree decl)
+{
+ while (TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl))
+ decl = USING_DECL_DECLS (decl);
+ return decl;
+}
+
/* BINDING records an existing declaration for a name in the current scope.
But, DECL is another declaration for that same identifier in the
same scope. This is the `struct stat' hack whereby a non-typedef
@@ -417,29 +428,46 @@ supplement_binding_1 (cxx_binding *binding, tree decl)
{
tree bval = binding->value;
bool ok = true;
-
- if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
+ tree target_bval = strip_using_decl (bval);
+ tree target_decl = strip_using_decl (decl);
+
+ if (TREE_CODE (target_decl) == TYPE_DECL && DECL_ARTIFICIAL (target_decl)
+ && target_decl != target_bval
+ && (TREE_CODE (target_bval) != TYPE_DECL
+ /* We allow pushing an enum multiple times in a class
+ template in order to handle late matching of underlying
+ type on an opaque-enum-declaration followed by an
+ enum-specifier. */
+ || (TREE_CODE (TREE_TYPE (target_decl)) == ENUMERAL_TYPE
+ && TREE_CODE (TREE_TYPE (target_bval)) == ENUMERAL_TYPE
+ && (dependent_type_p (ENUM_UNDERLYING_TYPE
+ (TREE_TYPE (target_decl)))
+ || dependent_type_p (ENUM_UNDERLYING_TYPE
+ (TREE_TYPE (target_bval)))))))
/* The new name is the type name. */
binding->type = decl;
- else if (/* BVAL is null when push_class_level_binding moves an
- inherited type-binding out of the way to make room for a
- new value binding. */
- !bval
- /* BVAL is error_mark_node when DECL's name has been used
- in a non-class scope prior declaration. In that case,
- we should have already issued a diagnostic; for graceful
- error recovery purpose, pretend this was the intended
- declaration for that name. */
- || bval == error_mark_node
- /* If BVAL is anticipated but has not yet been declared,
- pretend it is not there at all. */
- || (TREE_CODE (bval) == FUNCTION_DECL
- && DECL_ANTICIPATED (bval)
- && !DECL_HIDDEN_FRIEND_P (bval)))
+ else if (/* TARGET_BVAL is null when push_class_level_binding moves
+ an inherited type-binding out of the way to make room
+ for a new value binding. */
+ !target_bval
+ /* TARGET_BVAL is error_mark_node when TARGET_DECL's name
+ has been used in a non-class scope prior declaration.
+ In that case, we should have already issued a
+ diagnostic; for graceful error recovery purpose, pretend
+ this was the intended declaration for that name. */
+ || target_bval == error_mark_node
+ /* If TARGET_BVAL is anticipated but has not yet been
+ declared, pretend it is not there at all. */
+ || (TREE_CODE (target_bval) == FUNCTION_DECL
+ && DECL_ANTICIPATED (target_bval)
+ && !DECL_HIDDEN_FRIEND_P (target_bval)))
binding->value = decl;
- else if (TREE_CODE (bval) == TYPE_DECL && DECL_ARTIFICIAL (bval)
- && (TREE_CODE (decl) != TYPE_DECL
- || same_type_p (TREE_TYPE (decl), TREE_TYPE (bval))))
+ else if (TREE_CODE (target_bval) == TYPE_DECL
+ && DECL_ARTIFICIAL (target_bval)
+ && target_decl != target_bval
+ && (TREE_CODE (target_decl) != TYPE_DECL
+ || same_type_p (TREE_TYPE (target_decl),
+ TREE_TYPE (target_bval))))
{
/* The old binding was a type name. It was placed in
VALUE field because it was thought, at the point it was
@@ -450,15 +478,15 @@ supplement_binding_1 (cxx_binding *binding, tree decl)
binding->value = decl;
binding->value_is_inherited = false;
}
- else if (TREE_CODE (bval) == TYPE_DECL
- && TREE_CODE (decl) == TYPE_DECL
- && DECL_NAME (decl) == DECL_NAME (bval)
+ else if (TREE_CODE (target_bval) == TYPE_DECL
+ && TREE_CODE (target_decl) == TYPE_DECL
+ && DECL_NAME (target_decl) == DECL_NAME (target_bval)
&& binding->scope->kind != sk_class
- && (same_type_p (TREE_TYPE (decl), TREE_TYPE (bval))
+ && (same_type_p (TREE_TYPE (target_decl), TREE_TYPE (target_bval))
/* If either type involves template parameters, we must
wait until instantiation. */
- || uses_template_parms (TREE_TYPE (decl))
- || uses_template_parms (TREE_TYPE (bval))))
+ || uses_template_parms (TREE_TYPE (target_decl))
+ || uses_template_parms (TREE_TYPE (target_bval))))
/* We have two typedef-names, both naming the same type to have
the same name. In general, this is OK because of:
@@ -480,9 +508,10 @@ supplement_binding_1 (cxx_binding *binding, tree decl)
A member shall not be declared twice in the
member-specification. */
- else if (TREE_CODE (decl) == VAR_DECL && TREE_CODE (bval) == VAR_DECL
- && DECL_EXTERNAL (decl) && DECL_EXTERNAL (bval)
- && !DECL_CLASS_SCOPE_P (decl))
+ else if (TREE_CODE (target_decl) == VAR_DECL
+ && TREE_CODE (target_bval) == VAR_DECL
+ && DECL_EXTERNAL (target_decl) && DECL_EXTERNAL (target_bval)
+ && !DECL_CLASS_SCOPE_P (target_decl))
{
duplicate_decls (decl, binding->value, /*newdecl_is_friend=*/false);
ok = false;
@@ -501,14 +530,30 @@ supplement_binding_1 (cxx_binding *binding, tree decl)
ok = false;
else
{
- error ("declaration of %q#D", decl);
- error ("conflicts with previous declaration %q+#D", bval);
+ diagnose_name_conflict (decl, bval);
ok = false;
}
return ok;
}
+/* Diagnose a name conflict between DECL and BVAL. */
+
+static void
+diagnose_name_conflict (tree decl, tree bval)
+{
+ if (TREE_CODE (decl) == TREE_CODE (bval)
+ && (TREE_CODE (decl) != TYPE_DECL
+ || (DECL_ARTIFICIAL (decl) && DECL_ARTIFICIAL (bval))
+ || (!DECL_ARTIFICIAL (decl) && !DECL_ARTIFICIAL (bval)))
+ && !is_overloaded_fn (decl))
+ error ("redeclaration of %q#D", decl);
+ else
+ error ("%q#D conflicts with a previous declaration", decl);
+
+ inform (input_location, "previous declaration %q+#D", bval);
+}
+
/* Wrapper for supplement_binding_1. */
static bool
@@ -3028,6 +3073,8 @@ push_class_level_binding_1 (tree name, tree x)
{
tree bval = binding->value;
tree old_decl = NULL_TREE;
+ tree target_decl = strip_using_decl (decl);
+ tree target_bval = strip_using_decl (bval);
if (INHERITED_VALUE_BINDING_P (binding))
{
@@ -3035,8 +3082,10 @@ push_class_level_binding_1 (tree name, tree x)
tag name, slide it over to make room for the new binding.
The old binding is still visible if explicitly qualified
with a class-key. */
- if (TREE_CODE (bval) == TYPE_DECL && DECL_ARTIFICIAL (bval)
- && !(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)))
+ if (TREE_CODE (target_bval) == TYPE_DECL
+ && DECL_ARTIFICIAL (target_bval)
+ && !(TREE_CODE (target_decl) == TYPE_DECL
+ && DECL_ARTIFICIAL (target_decl)))
{
old_decl = binding->type;
binding->type = bval;
@@ -3048,17 +3097,31 @@ push_class_level_binding_1 (tree name, tree x)
old_decl = bval;
/* Any inherited type declaration is hidden by the type
declaration in the derived class. */
- if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x))
+ if (TREE_CODE (target_decl) == TYPE_DECL
+ && DECL_ARTIFICIAL (target_decl))
binding->type = NULL_TREE;
}
}
- else if (TREE_CODE (x) == OVERLOAD && is_overloaded_fn (bval))
+ else if (TREE_CODE (target_decl) == OVERLOAD
+ && is_overloaded_fn (target_bval))
old_decl = bval;
- else if (TREE_CODE (x) == USING_DECL && TREE_CODE (bval) == USING_DECL)
+ else if (TREE_CODE (decl) == USING_DECL
+ && TREE_CODE (bval) == USING_DECL
+ && same_type_p (USING_DECL_SCOPE (decl),
+ USING_DECL_SCOPE (bval)))
+ /* This is a using redeclaration that will be diagnosed later
+ in supplement_binding */
+ ;
+ else if (TREE_CODE (decl) == USING_DECL
+ && TREE_CODE (bval) == USING_DECL
+ && DECL_DEPENDENT_P (decl)
+ && DECL_DEPENDENT_P (bval))
return true;
- else if (TREE_CODE (x) == USING_DECL && is_overloaded_fn (bval))
+ else if (TREE_CODE (decl) == USING_DECL
+ && is_overloaded_fn (target_bval))
old_decl = bval;
- else if (TREE_CODE (bval) == USING_DECL && is_overloaded_fn (x))
+ else if (TREE_CODE (bval) == USING_DECL
+ && is_overloaded_fn (target_decl))
return true;
if (old_decl && binding->scope == class_binding_level)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index fc8f3c82bac..2fdd6753d08 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -3547,40 +3547,79 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
return value;
}
+/* Look up a literal operator with the name and the exact arguments. */
+
+static tree
+lookup_literal_operator (tree name, VEC(tree,gc) *args)
+{
+ tree decl, fns;
+ decl = lookup_name (name);
+ if (!decl || decl == error_mark_node)
+ return error_mark_node;
+
+ for (fns = decl; fns; fns = OVL_NEXT (fns))
+ {
+ unsigned int ix;
+ bool found = true;
+ tree fn = OVL_CURRENT (fns);
+ tree argtypes = NULL_TREE;
+ argtypes = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ if (argtypes != NULL_TREE)
+ {
+ for (ix = 0; ix < VEC_length (tree, args) && argtypes != NULL_TREE;
+ ++ix, argtypes = TREE_CHAIN (argtypes))
+ {
+ tree targ = TREE_VALUE (argtypes);
+ tree tparm = TREE_TYPE (VEC_index (tree, args, ix));
+ bool ptr = TREE_CODE (targ) == POINTER_TYPE;
+ bool arr = TREE_CODE (tparm) == ARRAY_TYPE;
+ if ((ptr || arr || !same_type_p (targ, tparm))
+ && (!ptr || !arr
+ || !same_type_p (TREE_TYPE (targ),
+ TREE_TYPE (tparm))))
+ found = false;
+ }
+ if (found)
+ return fn;
+ }
+ }
+
+ return error_mark_node;
+}
+
/* 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));
+ cp_token *token = cp_lexer_consume_token (parser->lexer);
+ tree literal = token->u.value;
+ tree suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal);
+ tree value = USERDEF_LITERAL_VALUE (literal);
+ tree name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id));
+ tree decl, result;
/* 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);
+ VEC(tree,gc) *args = make_tree_vector ();
+ VEC_safe_push (tree, gc, args, value);
+ decl = lookup_literal_operator (name, args);
if (!decl || decl == error_mark_node)
{
- error ("unable to find user-defined character literal operator %qD",
- name);
- release_tree_vector (vec);
+ error ("unable to find character literal operator %qD with %qT argument",
+ name, TREE_TYPE (value));
+ release_tree_vector (args);
return error_mark_node;
}
- result = finish_call_expr (decl, &vec, false, true, tf_warning_or_error);
- release_tree_vector (vec);
+ result = finish_call_expr (decl, &args, false, true, tf_warning_or_error);
+ release_tree_vector (args);
+ if (result != error_mark_node)
+ return result;
- return result;
+ error ("unable to find character literal operator %qD with %qT argument",
+ name, TREE_TYPE (value));
+ return error_mark_node;
}
/* A subroutine of cp_parser_userdef_numeric_literal to
@@ -3615,26 +3654,20 @@ make_char_string_pack (tree value)
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;
+ cp_token *token = cp_lexer_consume_token (parser->lexer);
+ tree literal = token->u.value;
+ tree suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal);
+ tree value = USERDEF_LITERAL_VALUE (literal);
+ tree num_string = USERDEF_LITERAL_NUM_STRING (literal);
+ tree name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id));
+ tree decl, result;
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. */
+ /* Look for a literal operator taking the exact type of numeric argument
+ as the literal value. */
args = make_tree_vector ();
VEC_safe_push (tree, gc, args, value);
- decl = lookup_function_nonclass (name, args, /*block_p=*/false);
+ decl = lookup_literal_operator (name, args);
if (decl && decl != error_mark_node)
{
result = finish_call_expr (decl, &args, false, true, tf_none);
@@ -3651,7 +3684,7 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
in string format. */
args = make_tree_vector ();
VEC_safe_push (tree, gc, args, num_string);
- decl = lookup_function_nonclass (name, args, /*block_p=*/false);
+ decl = lookup_literal_operator (name, args);
if (decl && decl != error_mark_node)
{
result = finish_call_expr (decl, &args, false, true, tf_none);
@@ -3667,7 +3700,7 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
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);
+ decl = lookup_literal_operator (name, args);
if (decl && decl != error_mark_node)
{
tree tmpl_args = make_char_string_pack (num_string);
@@ -3681,10 +3714,8 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
}
release_tree_vector (args);
- if (result == error_mark_node)
- error ("unable to find user-defined numeric literal operator %qD", name);
-
- return result;
+ error ("unable to find numeric literal operator %qD", name);
+ return error_mark_node;
}
/* Parse a user-defined string constant. Returns a call to a user-defined
@@ -3694,38 +3725,34 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
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)
+ tree literal = token->u.value;
+ tree suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal);
+ tree name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id));
+ tree value = USERDEF_LITERAL_VALUE (literal);
+ int len = TREE_STRING_LENGTH (value)
/ TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (value)))) - 1;
+ tree decl, result;
+
/* 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);
+ VEC(tree,gc) *args = make_tree_vector ();
+ VEC_safe_push (tree, gc, args, value);
+ VEC_safe_push (tree, gc, args, build_int_cst (size_type_node, len));
+ decl = lookup_name (name);
if (!decl || decl == error_mark_node)
{
- error ("unable to find user-defined string literal operator %qD", name);
- release_tree_vector (vec);
+ error ("unable to find string literal operator %qD", name);
+ release_tree_vector (args);
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);
+ result = finish_call_expr (decl, &args, false, true, tf_none);
+ release_tree_vector (args);
+ if (result != error_mark_node)
+ return result;
- return result;
+ error ("unable to find string literal operator %qD with %qT, %qT arguments",
+ name, TREE_TYPE (value), size_type_node);
+ return error_mark_node;
}
@@ -13758,6 +13785,9 @@ cp_parser_nonclass_name (cp_parser* parser)
/* Look up the type-name. */
type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location);
+ /* If it is a using decl, use its underlying decl. */
+ type_decl = strip_using_decl (type_decl);
+
if (TREE_CODE (type_decl) != TYPE_DECL
&& (objc_is_id (identifier) || objc_is_class_name (identifier)))
{
@@ -13930,7 +13960,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
else if (tag_type == typename_type && TREE_CODE (decl) != TYPE_DECL)
type = NULL_TREE;
else
- type = TREE_TYPE (decl);
+ type = check_elaborated_type_specifier (tag_type, decl,
+ /*allow_template_p=*/true);
}
if (!type)
@@ -14937,6 +14968,7 @@ cp_parser_alias_declaration (cp_parser* parser)
cp_declarator *declarator;
cp_decl_specifier_seq decl_specs;
bool member_p;
+ const char *saved_message = NULL;
/* Look for the `using' keyword. */
cp_parser_require_keyword (parser, RID_USING, RT_USING);
@@ -14945,7 +14977,35 @@ cp_parser_alias_declaration (cp_parser* parser)
attributes = cp_parser_attributes_opt (parser);
cp_parser_require (parser, CPP_EQ, RT_EQ);
+ /* Now we are going to parse the type-id of the declaration. */
+
+ /*
+ [dcl.type]/3 says:
+
+ "A type-specifier-seq shall not define a class or enumeration
+ unless it appears in the type-id of an alias-declaration (7.1.3) that
+ is not the declaration of a template-declaration."
+
+ In other words, if we currently are in an alias template, the
+ type-id should not define a type.
+
+ So let's set parser->type_definition_forbidden_message in that
+ case; cp_parser_check_type_definition (called by
+ cp_parser_class_specifier) will then emit an error if a type is
+ defined in the type-id. */
+ if (parser->num_template_parameter_lists)
+ {
+ saved_message = parser->type_definition_forbidden_message;
+ parser->type_definition_forbidden_message =
+ G_("types may not be defined in alias template declarations");
+ }
+
type = cp_parser_type_id (parser);
+
+ /* Restore the error message if need be. */
+ if (parser->num_template_parameter_lists)
+ parser->type_definition_forbidden_message = saved_message;
+
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
if (cp_parser_error_occurred (parser))
@@ -26808,7 +26868,7 @@ cp_parser_transaction_expression (cp_parser *parser, enum rid keyword)
unsigned char old_in = parser->in_transaction;
unsigned char this_in = 1;
cp_token *token;
- tree ret;
+ tree expr;
gcc_assert (keyword == RID_TRANSACTION_ATOMIC
|| keyword == RID_TRANSACTION_RELAXED);
@@ -26829,22 +26889,19 @@ cp_parser_transaction_expression (cp_parser *parser, enum rid keyword)
this_in |= TM_STMT_ATTR_RELAXED;
parser->in_transaction = this_in;
- if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
- {
- tree expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
- ret = build_transaction_expr (token->location, expr, this_in);
- }
- else
- {
- cp_parser_error (parser, "expected %<(%>");
- ret = error_mark_node;
- }
+ cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+
+ expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+ finish_parenthesized_expr (expr);
+ expr = build_transaction_expr (token->location, expr, this_in);
+
+ cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
parser->in_transaction = old_in;
if (cp_parser_non_integral_constant_expression (parser, NIC_TRANSACTION))
return error_mark_node;
- return (flag_tm ? ret : error_mark_node);
+ return (flag_tm ? expr : error_mark_node);
}
/* Parse a function-transaction-block.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 97380260ae4..47250807577 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -1534,7 +1534,8 @@ iterative_hash_template_arg (tree arg, hashval_t val)
case TYPE_PACK_EXPANSION:
case EXPR_PACK_EXPANSION:
- return iterative_hash_template_arg (PACK_EXPANSION_PATTERN (arg), val);
+ val = iterative_hash_template_arg (PACK_EXPANSION_PATTERN (arg), val);
+ return iterative_hash_template_arg (PACK_EXPANSION_EXTRA_ARGS (arg), val);
case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK:
@@ -2870,7 +2871,7 @@ primary_template_instantiation_p (const_tree t)
return DECL_LANG_SPECIFIC (t)
&& DECL_TEMPLATE_INSTANTIATION (t)
&& PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t));
- else if (CLASS_TYPE_P (t))
+ else if (CLASS_TYPE_P (t) && !TYPE_DECL_ALIAS_P (TYPE_NAME (t)))
return CLASSTYPE_TEMPLATE_INSTANTIATION (t)
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t));
else if (TYPE_P (t)
@@ -5501,7 +5502,7 @@ unify_inconsistency (bool explain_p, tree parm, tree first, tree second)
{
if (explain_p)
inform (input_location,
- " deduced conflicting types for parameter %qT (%qT and %qT)",
+ " conflicting deductions for parameter %qE (%qE and %qE)",
parm, first, second);
return 1;
}
@@ -6902,9 +6903,11 @@ template_args_equal (tree ot, tree nt)
/* For member templates */
return TREE_CODE (ot) == TREE_VEC && comp_template_args (ot, nt);
else if (PACK_EXPANSION_P (ot))
- return PACK_EXPANSION_P (nt)
- && template_args_equal (PACK_EXPANSION_PATTERN (ot),
- PACK_EXPANSION_PATTERN (nt));
+ return (PACK_EXPANSION_P (nt)
+ && template_args_equal (PACK_EXPANSION_PATTERN (ot),
+ PACK_EXPANSION_PATTERN (nt))
+ && template_args_equal (PACK_EXPANSION_EXTRA_ARGS (ot),
+ PACK_EXPANSION_EXTRA_ARGS (nt)));
else if (ARGUMENT_PACK_P (ot))
{
int i, len;
@@ -6954,6 +6957,12 @@ comp_template_args_with_info (tree oldargs, tree newargs,
{
int i;
+ if (oldargs == newargs)
+ return 1;
+
+ if (!oldargs || !newargs)
+ return 0;
+
if (TREE_VEC_LENGTH (oldargs) != TREE_VEC_LENGTH (newargs))
return 0;
@@ -7270,6 +7279,12 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
int is_dependent_type;
int use_partial_inst_tmpl = false;
+ if (template_type == error_mark_node)
+ /* An error occured while building the template TEMPL, and a
+ diagnostic has most certainly been emitted for that
+ already. Let's propagate that error. */
+ return error_mark_node;
+
gen_tmpl = most_general_template (templ);
parmlist = DECL_TEMPLATE_PARMS (gen_tmpl);
parm_depth = TMPL_PARMS_DEPTH (parmlist);
@@ -9088,14 +9103,20 @@ instantiate_class_template_1 (tree type)
if (CLASSTYPE_LAMBDA_EXPR (type))
{
- tree lambda = CLASSTYPE_LAMBDA_EXPR (type);
- if (LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda))
+ tree decl = lambda_function (type);
+ if (decl)
{
- apply_lambda_return_type (lambda, void_type_node);
- LAMBDA_EXPR_RETURN_TYPE (lambda) = NULL_TREE;
+ tree lambda = CLASSTYPE_LAMBDA_EXPR (type);
+ if (LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda))
+ {
+ apply_lambda_return_type (lambda, void_type_node);
+ LAMBDA_EXPR_RETURN_TYPE (lambda) = NULL_TREE;
+ }
+ instantiate_decl (decl, false, false);
+ maybe_add_lambda_conv_op (type);
}
- instantiate_decl (lambda_function (type), false, false);
- maybe_add_lambda_conv_op (type);
+ else
+ gcc_assert (errorcount);
}
/* Set the file and line number information to whatever is given for
@@ -9235,13 +9256,21 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
tree pattern;
tree pack, packs = NULL_TREE;
bool unsubstituted_packs = false;
+ bool real_packs = false;
+ int missing_level = 0;
int i, len = -1;
tree result;
htab_t saved_local_specializations = NULL;
+ int levels;
gcc_assert (PACK_EXPANSION_P (t));
pattern = PACK_EXPANSION_PATTERN (t);
+ /* Add in any args remembered from an earlier partial instantiation. */
+ args = add_to_template_args (PACK_EXPANSION_EXTRA_ARGS (t), args);
+
+ levels = TMPL_ARGS_DEPTH (args);
+
/* Determine the argument packs that will instantiate the parameter
packs used in the expansion expression. While we're at it,
compute the number of arguments to be expanded and make sure it
@@ -9252,6 +9281,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
tree parm_pack = TREE_VALUE (pack);
tree arg_pack = NULL_TREE;
tree orig_arg = NULL_TREE;
+ int level = 0;
if (TREE_CODE (parm_pack) == BASES)
{
@@ -9284,10 +9314,9 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
}
else
{
- int level, idx, levels;
+ int idx;
template_parm_level_and_index (parm_pack, &level, &idx);
- levels = TMPL_ARGS_DEPTH (args);
if (level <= levels)
arg_pack = TMPL_ARG (args, level, idx);
}
@@ -9327,7 +9356,9 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
len = my_len;
else if (len != my_len)
{
- if (TREE_CODE (t) == TYPE_PACK_EXPANSION)
+ if (!(complain & tf_error))
+ /* Fail quietly. */;
+ else if (TREE_CODE (t) == TYPE_PACK_EXPANSION)
error ("mismatched argument pack lengths while expanding "
"%<%T%>",
pattern);
@@ -9338,6 +9369,13 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
return error_mark_node;
}
+ if (TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack)) == 1
+ && PACK_EXPANSION_P (TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack),
+ 0)))
+ /* This isn't a real argument pack yet. */;
+ else
+ real_packs = true;
+
/* Keep track of the parameter packs and their corresponding
argument packs. */
packs = tree_cons (parm_pack, arg_pack, packs);
@@ -9345,25 +9383,57 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
}
else
{
- /* We can't substitute for this parameter pack. */
+ /* We can't substitute for this parameter pack. We use a flag as
+ well as the missing_level counter because function parameter
+ packs don't have a level. */
unsubstituted_packs = true;
- break;
+ if (!missing_level || missing_level > level)
+ missing_level = level;
}
}
/* We cannot expand this expansion expression, because we don't have
- all of the argument packs we need. Substitute into the pattern
- and return a PACK_EXPANSION_*. The caller will need to deal with
- that. */
+ all of the argument packs we need. */
if (unsubstituted_packs)
{
- tree new_pat;
- if (TREE_CODE (t) == EXPR_PACK_EXPANSION)
- new_pat = tsubst_expr (pattern, args, complain, in_decl,
- /*integral_constant_expression_p=*/false);
+ if (real_packs)
+ {
+ /* We got some full packs, but we can't substitute them in until we
+ have values for all the packs. So remember these until then. */
+ tree save_args;
+
+ t = make_pack_expansion (pattern);
+
+ /* The call to add_to_template_args above assumes no overlap
+ between saved args and new args, so prune away any fake
+ args, i.e. those that satisfied arg_from_parm_pack_p above. */
+ if (missing_level && levels >= missing_level)
+ {
+ gcc_assert (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)
+ && missing_level > 1);
+ TREE_VEC_LENGTH (args) = missing_level - 1;
+ save_args = copy_node (args);
+ TREE_VEC_LENGTH (args) = levels;
+ }
+ else
+ save_args = args;
+
+ PACK_EXPANSION_EXTRA_ARGS (t) = save_args;
+ }
else
- new_pat = tsubst (pattern, args, complain, in_decl);
- return make_pack_expansion (new_pat);
+ {
+ /* There were no real arguments, we're just replacing a parameter
+ pack with another version of itself. Substitute into the
+ pattern and return a PACK_EXPANSION_*. The caller will need to
+ deal with that. */
+ if (TREE_CODE (t) == EXPR_PACK_EXPANSION)
+ t = tsubst_expr (pattern, args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+ else
+ t = tsubst (pattern, args, complain, in_decl);
+ t = make_pack_expansion (t);
+ }
+ return t;
}
/* We could not find any argument packs that work. */
@@ -13387,6 +13457,10 @@ tsubst_copy_and_build (tree t,
return build_x_unary_op (TREE_CODE (t), RECUR (TREE_OPERAND (t, 0)),
complain);
+ case FIX_TRUNC_EXPR:
+ return cp_build_unary_op (FIX_TRUNC_EXPR, RECUR (TREE_OPERAND (t, 0)),
+ 0, complain);
+
case ADDR_EXPR:
op1 = TREE_OPERAND (t, 0);
if (TREE_CODE (op1) == LABEL_DECL)
@@ -14222,6 +14296,10 @@ tsubst_copy_and_build (tree t,
return r;
}
+ case TRANSACTION_EXPR:
+ return tsubst_expr(t, args, complain, in_decl,
+ integral_constant_expression_p);
+
default:
/* Handle Objective-C++ constructs, if appropriate. */
{
@@ -15208,9 +15286,13 @@ type_unification_real (tree tparms,
{
tree parm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
tree arg = TREE_PURPOSE (TREE_VEC_ELT (tparms, i));
+ location_t save_loc = input_location;
+ if (DECL_P (parm))
+ input_location = DECL_SOURCE_LOCATION (parm);
arg = tsubst_template_arg (arg, targs, complain, NULL_TREE);
arg = convert_template_argument (parm, arg, targs, complain,
i, NULL_TREE);
+ input_location = save_loc;
if (arg == error_mark_node)
return 1;
else
diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c
index fb05e136045..a66e695c1f7 100644
--- a/gcc/cp/ptree.c
+++ b/gcc/cp/ptree.c
@@ -104,6 +104,10 @@ cxx_print_type (FILE *file, tree node, int indent)
indent + 4);
return;
+ case TYPE_PACK_EXPANSION:
+ print_node (file, "args", PACK_EXPANSION_EXTRA_ARGS (node), indent + 4);
+ return;
+
default:
return;
}
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 7d9551c28bf..3894c685884 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -1,7 +1,7 @@
/* Breadth-first and depth-first routines for
searching multiple-inheritance lattice for GNU C++.
Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
+ 1999, 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
@@ -436,6 +436,14 @@ lookup_field_1 (tree type, tree name, bool want_type)
field = fields[i++];
while (i < hi && DECL_NAME (fields[i]) == name);
}
+
+ if (field)
+ {
+ field = strip_using_decl (field);
+ if (is_overloaded_fn (field))
+ field = NULL_TREE;
+ }
+
return field;
}
}
@@ -449,6 +457,8 @@ lookup_field_1 (tree type, tree name, bool want_type)
#endif /* GATHER_STATISTICS */
for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
{
+ tree decl = field;
+
#ifdef GATHER_STATISTICS
n_fields_searched++;
#endif /* GATHER_STATISTICS */
@@ -460,26 +470,20 @@ lookup_field_1 (tree type, tree name, bool want_type)
if (temp)
return temp;
}
- if (TREE_CODE (field) == USING_DECL)
+
+ if (TREE_CODE (decl) == USING_DECL
+ && DECL_NAME (decl) == name)
{
- /* We generally treat class-scope using-declarations as
- ARM-style access specifications, because support for the
- ISO semantics has not been implemented. So, in general,
- there's no reason to return a USING_DECL, and the rest of
- the compiler cannot handle that. Once the class is
- defined, USING_DECLs are purged from TYPE_FIELDS; see
- handle_using_decl. However, we make special efforts to
- make using-declarations in class templates and class
- template partial specializations work correctly. */
- if (!DECL_DEPENDENT_P (field))
+ decl = strip_using_decl (decl);
+ if (is_overloaded_fn (decl))
continue;
}
- if (DECL_NAME (field) == name
+ if (DECL_NAME (decl) == name
&& (!want_type
- || TREE_CODE (field) == TYPE_DECL
- || DECL_TYPE_TEMPLATE_P (field)))
- return field;
+ || TREE_CODE (decl) == TYPE_DECL
+ || DECL_TYPE_TEMPLATE_P (decl)))
+ return decl;
}
/* Not found. */
if (name == vptr_identifier)
@@ -1028,11 +1032,7 @@ lookup_field_r (tree binfo, void *data)
member with the same name, and if there's a function and a type
with the same name, the type is hidden by the function. */
if (!lfi->want_type)
- {
- int idx = lookup_fnfields_1 (type, lfi->name);
- if (idx >= 0)
- nval = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), idx);
- }
+ nval = lookup_fnfields_slot (type, lfi->name);
if (!nval)
/* Look for a data member or type. */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index e9da3817577..3c9853a3529 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2658,9 +2658,29 @@ finish_member_declaration (tree decl)
}
}
/* Enter the DECL into the scope of the class. */
- else if ((TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl))
- || pushdecl_class_level (decl))
+ else if (pushdecl_class_level (decl))
{
+ if (TREE_CODE (decl) == USING_DECL)
+ {
+ /* We need to add the target functions to the
+ CLASSTYPE_METHOD_VEC if an enclosing scope is a template
+ class, so that this function be found by lookup_fnfields_1
+ when the using declaration is not instantiated yet. */
+
+ tree target_decl = strip_using_decl (decl);
+ if (dependent_type_p (current_class_type)
+ && is_overloaded_fn (target_decl))
+ {
+ tree t = target_decl;
+ for (; t; t = OVL_NEXT (t))
+ add_method (current_class_type, OVL_CURRENT (t), decl);
+ }
+
+ /* For now, ignore class-scope USING_DECLS, so that
+ debugging backends do not see them. */
+ DECL_IGNORED_P (decl) = 1;
+ }
+
/* All TYPE_DECLs go at the end of TYPE_FIELDS. Ordinary fields
go at the beginning. The reason is that lookup_field_1
searches the list in order, and we want a field name to
@@ -5215,8 +5235,9 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
gcc_unreachable ();
case INTEGER_CST:
+ case PTRMEM_CST:
/* We can get here when the id-expression refers to an
- enumerator. */
+ enumerator or non-type template parameter. */
type = TREE_TYPE (expr);
break;
@@ -8158,6 +8179,10 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
case EXPR_STMT:
case BIND_EXPR:
case TRANSACTION_EXPR:
+ case IF_STMT:
+ case DO_STMT:
+ case FOR_STMT:
+ case WHILE_STMT:
if (flags & tf_error)
error ("expression %qE is not a constant-expression", t);
return false;
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 841029f3385..d206fd2ec24 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2993,11 +2993,13 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
case TYPE_PACK_EXPANSION:
WALK_SUBTREE (TREE_TYPE (*tp));
+ WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (*tp));
*walk_subtrees_p = 0;
break;
case EXPR_PACK_EXPANSION:
WALK_SUBTREE (TREE_OPERAND (*tp, 0));
+ WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (*tp));
*walk_subtrees_p = 0;
break;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 722cec5b5b9..9a5365c612c 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1329,8 +1329,10 @@ structural_comptypes (tree t1, tree t2, int strict)
break;
case TYPE_PACK_EXPANSION:
- return same_type_p (PACK_EXPANSION_PATTERN (t1),
- PACK_EXPANSION_PATTERN (t2));
+ return (same_type_p (PACK_EXPANSION_PATTERN (t1),
+ PACK_EXPANSION_PATTERN (t2))
+ && comp_template_args (PACK_EXPANSION_EXTRA_ARGS (t1),
+ PACK_EXPANSION_EXTRA_ARGS (t2)));
case DECLTYPE_TYPE:
if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t1)
@@ -2115,6 +2117,7 @@ build_class_member_access_expr (tree object, tree member,
tree object_type;
tree member_scope;
tree result = NULL_TREE;
+ tree using_decl = NULL_TREE;
if (error_operand_p (object) || error_operand_p (member))
return error_mark_node;
@@ -2343,6 +2346,11 @@ build_class_member_access_expr (tree object, tree member,
result = build2 (COMPOUND_EXPR, TREE_TYPE (result),
object, result);
}
+ else if ((using_decl = strip_using_decl (member)) != member)
+ result = build_class_member_access_expr (object,
+ using_decl,
+ access_path, preserve_reference,
+ complain);
else
{
if (complain & tf_error)
@@ -4048,6 +4056,13 @@ cp_build_binary_op (location_t location,
delta0,
integer_one_node,
complain);
+
+ if ((complain & tf_warning)
+ && c_inhibit_evaluation_warnings == 0
+ && !NULLPTR_TYPE_P (TREE_TYPE (op1)))
+ warning (OPT_Wzero_as_null_pointer_constant,
+ "zero as null pointer constant");
+
e2 = cp_build_binary_op (location,
EQ_EXPR, e2, integer_zero_node,
complain);
@@ -8417,9 +8432,8 @@ 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));
+ if (processing_template_decl || processing_specialization)
+ return argtypes == void_list_node;
else
{
tree argtype;
@@ -8488,7 +8502,7 @@ check_literal_operator_args (const_tree decl,
if (!argtype)
return false; /* Found ellipsis. */
- if (arity > max_arity)
+ if (arity != max_arity)
return false;
return true;
diff --git a/gcc/cprop.c b/gcc/cprop.c
index 9ee1efb1af6..01f40f0bc72 100644
--- a/gcc/cprop.c
+++ b/gcc/cprop.c
@@ -116,6 +116,11 @@ static struct hash_table_d set_hash_table;
/* Array of implicit set patterns indexed by basic block index. */
static rtx *implicit_sets;
+/* Array of indexes of expressions for implicit set patterns indexed by basic
+ block index. In other words, implicit_set_indexes[i] is the bitmap_index
+ of the expression whose RTX is implicit_sets[i]. */
+static int *implicit_set_indexes;
+
/* Bitmap containing one bit for each register in the program.
Used when performing GCSE to track which registers have been set since
the start or end of the basic block while traversing that block. */
@@ -177,10 +182,12 @@ hash_set (int regno, int hash_table_size)
/* Insert assignment DEST:=SET from INSN in the hash table.
DEST is a register and SET is a register or a suitable constant.
If the assignment is already present in the table, record it as
- the last occurrence in INSN's basic block. */
+ the last occurrence in INSN's basic block.
+ IMPLICIT is true if it's an implicit set, false otherwise. */
static void
-insert_set_in_table (rtx dest, rtx src, rtx insn, struct hash_table_d *table)
+insert_set_in_table (rtx dest, rtx src, rtx insn, struct hash_table_d *table,
+ bool implicit)
{
bool found = false;
unsigned int hash;
@@ -243,6 +250,10 @@ insert_set_in_table (rtx dest, rtx src, rtx insn, struct hash_table_d *table)
cur_occr->next = cur_expr->avail_occr;
cur_expr->avail_occr = cur_occr;
}
+
+ /* Record bitmap_index of the implicit set in implicit_set_indexes. */
+ if (implicit)
+ implicit_set_indexes[BLOCK_FOR_INSN(insn)->index] = cur_expr->bitmap_index;
}
/* Determine whether the rtx X should be treated as a constant for CPROP.
@@ -255,10 +266,11 @@ cprop_constant_p (const_rtx x)
return CONSTANT_P (x) && (GET_CODE (x) != CONST || shared_const_p (x));
}
-/* Scan SET present in INSN and add an entry to the hash TABLE. */
+/* Scan SET present in INSN and add an entry to the hash TABLE.
+ IMPLICIT is true if it's an implicit set, false otherwise. */
static void
-hash_scan_set (rtx set, rtx insn, struct hash_table_d *table)
+hash_scan_set (rtx set, rtx insn, struct hash_table_d *table, bool implicit)
{
rtx src = SET_SRC (set);
rtx dest = SET_DEST (set);
@@ -294,7 +306,7 @@ hash_scan_set (rtx set, rtx insn, struct hash_table_d *table)
&& ! HARD_REGISTER_P (src)
&& reg_available_p (src, insn))
|| cprop_constant_p (src))
- insert_set_in_table (dest, src, insn, table);
+ insert_set_in_table (dest, src, insn, table, implicit);
}
}
@@ -310,14 +322,14 @@ hash_scan_insn (rtx insn, struct hash_table_d *table)
what's been modified. */
if (GET_CODE (pat) == SET)
- hash_scan_set (pat, insn, table);
+ hash_scan_set (pat, insn, table, false);
else if (GET_CODE (pat) == PARALLEL)
for (i = 0; i < XVECLEN (pat, 0); i++)
{
rtx x = XVECEXP (pat, 0, i);
if (GET_CODE (x) == SET)
- hash_scan_set (x, insn, table);
+ hash_scan_set (x, insn, table, false);
}
}
@@ -421,7 +433,7 @@ compute_hash_table_work (struct hash_table_d *table)
/* Insert implicit sets in the hash table, pretending they appear as
insns at the head of the basic block. */
if (implicit_sets[bb->index] != NULL_RTX)
- hash_scan_set (implicit_sets[bb->index], BB_HEAD (bb), table);
+ hash_scan_set (implicit_sets[bb->index], BB_HEAD (bb), table, true);
}
FREE_REG_SET (reg_set_bitmap);
@@ -633,8 +645,22 @@ compute_local_properties (sbitmap *kill, sbitmap *comp,
static void
compute_cprop_data (void)
{
+ basic_block bb;
+
compute_local_properties (cprop_kill, cprop_avloc, &set_hash_table);
compute_available (cprop_avloc, cprop_kill, cprop_avout, cprop_avin);
+
+ /* Merge implicit sets into CPROP_AVIN. They are always available at the
+ entry of their basic block. We need to do this because 1) implicit sets
+ aren't recorded for the local pass so they cannot be propagated within
+ their basic block by this pass and 2) the global pass would otherwise
+ propagate them only in the successors of their basic block. */
+ FOR_EACH_BB (bb)
+ {
+ int index = implicit_set_indexes[bb->index];
+ if (index != -1)
+ SET_BIT (cprop_avin[bb->index], index);
+ }
}
/* Copy/constant propagation. */
@@ -1727,6 +1753,7 @@ is_too_expensive (const char *pass)
static int
one_cprop_pass (void)
{
+ int i;
int changed = 0;
/* Return if there's nothing to do, or it is too expensive. */
@@ -1774,6 +1801,11 @@ one_cprop_pass (void)
if (changed)
df_analyze ();
+ /* Initialize implicit_set_indexes array. */
+ implicit_set_indexes = XNEWVEC (int, last_basic_block);
+ for (i = 0; i < last_basic_block; i++)
+ implicit_set_indexes[i] = -1;
+
alloc_hash_table (&set_hash_table);
compute_hash_table (&set_hash_table);
@@ -1791,6 +1823,9 @@ one_cprop_pass (void)
alloc_cprop_mem (last_basic_block, set_hash_table.n_elems);
compute_cprop_data ();
+ free (implicit_set_indexes);
+ implicit_set_indexes = NULL;
+
/* Allocate vars to track sets of regs. */
reg_set_bitmap = ALLOC_REG_SET (NULL);
@@ -1820,6 +1855,11 @@ one_cprop_pass (void)
FREE_REG_SET (reg_set_bitmap);
free_cprop_mem ();
}
+ else
+ {
+ free (implicit_set_indexes);
+ implicit_set_indexes = NULL;
+ }
free_hash_table (&set_hash_table);
obstack_free (&cprop_obstack, NULL);
diff --git a/gcc/doc/contrib.texi b/gcc/doc/contrib.texi
index f76cce8d234..ffefecc8607 100644
--- a/gcc/doc/contrib.texi
+++ b/gcc/doc/contrib.texi
@@ -66,6 +66,10 @@ improved alias analysis, plus migrating GCC to Bugzilla.
Geoff Berry for his Java object serialization work and various patches.
@item
+David Binderman tests weekly snapshots of GCC trunk against Fedora Rawhide
+for several architectures.
+
+@item
Uros Bizjak for the implementation of x87 math built-in functions and
for various middle end and i386 back end improvements and bug fixes.
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 15238c1b39e..d52f9a0cf29 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -8594,11 +8594,41 @@ implements
void __builtin_avr_delay_cycles (unsigned long ticks)
@end smallexample
+@noindent
@code{ticks} is the number of ticks to delay execution. Note that this
built-in does not take into account the effect of interrupts which
might increase delay time. @code{ticks} must be a compile time
integer constant; delays with a variable number of cycles are not supported.
+@smallexample
+ unsigned char __builtin_avr_map8 (unsigned long map, unsigned char val)
+@end smallexample
+
+@noindent
+Each bit of the result is copied from a specific bit of @code{val}.
+@code{map} is a compile time constant that represents a map composed
+of 8 nibbles (4-bit groups):
+The @var{n}-th nibble of @code{map} specifies which bit of @code{val}
+is to be moved to the @var{n}-th bit of the result.
+For example, @code{map = 0x76543210} represents identity: The MSB of
+the result is read from the 7-th bit of @code{val}, the LSB is
+read from the 0-th bit to @code{val}, etc.
+Two more examples: @code{0x01234567} reverses the bit order and
+@code{0x32107654} is equivalent to a @code{swap} instruction.
+
+@noindent
+One typical use case for this and the following built-in is adjusting input and
+output values to non-contiguous port layouts.
+
+@smallexample
+ unsigned int __builtin_avr_map16 (unsigned long long map, unsigned int val)
+@end smallexample
+
+@noindent
+Similar to the previous built-in except that it operates on @code{int}
+and thus 16 bits are involved. Again, @code{map} must be a compile
+time constant.
+
@node Blackfin Built-in Functions
@subsection Blackfin Built-in Functions
@@ -9384,6 +9414,7 @@ v2df __builtin_ia32_loadlpd (v2df, double const *)
int __builtin_ia32_movmskpd (v2df)
int __builtin_ia32_pmovmskb128 (v16qi)
void __builtin_ia32_movnti (int *, int)
+void __builtin_ia32_movnti64 (long long int *, long long int)
void __builtin_ia32_movntpd (double *, v2df)
void __builtin_ia32_movntdq (v2df *, v2df)
v4si __builtin_ia32_pshufd (v4si, int)
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 1daddb865e4..46c5824cc71 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -1298,8 +1298,7 @@ experimental option which may become the default in a later release.
@item --enable-build-poststage1-with-cxx
When bootstrapping, build stages 2 and 3 of GCC using a C++ compiler
rather than a C compiler. Stage 1 is still built with a C compiler.
-This is an experimental option which may become the default in a later
-release. This is enabled by default and may be disabled using
+This is enabled by default and may be disabled using
@option{--disable-build-poststage1-with-cxx}.
@item --enable-maintainer-mode
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 1fc44372e32..4e6edb9414e 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -6731,13 +6731,16 @@ rule generates a better code.
Use specified regions for the integrated register allocator. The
@var{region} argument should be one of @code{all}, @code{mixed}, or
@code{one}. The first value means using all loops as register
-allocation regions, the second value which is the default means using
-all loops except for loops with small register pressure as the
-regions, and third one means using all function as a single region.
-The first value can give best result for machines with small size and
-irregular register set, the third one results in faster and generates
-decent code and the smallest size code, and the default value usually
-give the best results in most cases and for most architectures.
+allocation regions, the second value which is enabled by default when
+compiling with optimization for speed (@option{-O}, @option{-O2},
+@dots{}) means using all loops except for loops with small register
+pressure as the regions, and third one which is enabled by default for
+@option{-Os} or @option{-O0} means using all function as a single
+region. The first value can give best result for machines with small
+size and irregular register set, the third one results in faster and
+generates decent code and the smallest size code, and the second value
+usually give the best results in most cases and for most
+architectures.
@item -fira-loop-pressure
@opindex fira-loop-pressure
@@ -12803,6 +12806,15 @@ Improved versions of k8, opteron and athlon64 with SSE3 instruction set support.
AMD Family 10h core based CPUs with x86-64 instruction set support. (This
supersets MMX, SSE, SSE2, SSE3, SSE4A, 3DNow!, enhanced 3DNow!, ABM and 64-bit
instruction set extensions.)
+@item bdver1
+AMD Family 15h core based CPUs with x86-64 instruction set support. (This
+supersets FMA4, AVX, XOP, LWP, AES, PCL_MUL, CX16, MMX, SSE, SSE2, SSE3, SSE4A,
+SSSE3, SSE4.1, SSE4.2, 3DNow!, enhanced 3DNow!, ABM and 64-bit
+instruction set extensions.)
+@item btver1
+AMD Family 14h core based CPUs with x86-64 instruction set support. (This
+supersets MMX, SSE, SSE2, SSE3, SSSE3, SSE4A, CX16, ABM and 64-bit
+instruction set extensions.)
@item winchip-c6
IDT Winchip C6 CPU, dealt in same way as i486 with additional MMX instruction
set support.
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 10fd876fd09..c079ce29b7e 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -7090,6 +7090,10 @@ section names for mergeable constant data. Define this macro to override
the string if a different section name should be used.
@end deftypevr
+@deftypefn {Target Hook} {section *} TARGET_ASM_TM_CLONE_TABLE_SECTION (void)
+Return the section that should be used for transactional memory clone tables.
+@end deftypefn
+
@deftypefn {Target Hook} {section *} TARGET_ASM_SELECT_RTX_SECTION (enum machine_mode @var{mode}, rtx @var{x}, unsigned HOST_WIDE_INT @var{align})
Return the section into which a constant @var{x}, of mode @var{mode},
should be placed. You can assume that @var{x} is some kind of
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index cebeb1fa777..d03d7f656a2 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -7013,6 +7013,8 @@ otherwise.
@hook TARGET_ASM_MERGEABLE_RODATA_PREFIX
+@hook TARGET_ASM_TM_CLONE_TABLE_SECTION
+
@hook TARGET_ASM_SELECT_RTX_SECTION
Return the section into which a constant @var{x}, of mode @var{mode},
should be placed. You can assume that @var{x} is some kind of
diff --git a/gcc/expr.c b/gcc/expr.c
index 84cfe5c23ee..8d3a0f671a8 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -9740,11 +9740,16 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
&& modifier != EXPAND_CONST_ADDRESS
&& modifier != EXPAND_INITIALIZER)
/* If the field is volatile, we always want an aligned
- access. Only do this if the access is not already naturally
+ access. Do this in following two situations:
+ 1. the access is not already naturally
aligned, otherwise "normal" (non-bitfield) volatile fields
- become non-addressable. */
+ become non-addressable.
+ 2. the bitsize is narrower than the access size. Need
+ to extract bitfields from the access. */
|| (volatilep && flag_strict_volatile_bitfields > 0
- && (bitpos % GET_MODE_ALIGNMENT (mode) != 0))
+ && (bitpos % GET_MODE_ALIGNMENT (mode) != 0
+ || (mode1 != BLKmode
+ && bitsize < GET_MODE_SIZE (mode1) * BITS_PER_UNIT)))
/* If the field isn't aligned enough to fetch as a memref,
fetch it as a bit field. */
|| (mode1 != BLKmode
diff --git a/gcc/expr.h b/gcc/expr.h
index 2cc8152c740..7a323bacd6a 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -214,12 +214,15 @@ rtx emit_conditional_add (rtx, enum rtx_code, rtx, rtx, enum machine_mode,
rtx expand_sync_operation (rtx, rtx, enum rtx_code);
rtx expand_sync_fetch_operation (rtx, rtx, enum rtx_code, bool, rtx);
+rtx expand_sync_lock_test_and_set (rtx, rtx, rtx);
-rtx expand_atomic_exchange (rtx, rtx, rtx, enum memmodel, bool);
+rtx expand_atomic_exchange (rtx, rtx, rtx, enum memmodel);
rtx expand_atomic_load (rtx, rtx, enum memmodel);
rtx expand_atomic_store (rtx, rtx, enum memmodel, bool);
rtx expand_atomic_fetch_op (rtx, rtx, rtx, enum rtx_code, enum memmodel,
bool);
+rtx expand_atomic_test_and_set (rtx, rtx, enum memmodel);
+rtx expand_atomic_clear (rtx, enum memmodel);
void expand_atomic_thread_fence (enum memmodel);
void expand_atomic_signal_fence (enum memmodel);
@@ -254,7 +257,6 @@ extern void expand_builtin_setjmp_receiver (rtx);
extern rtx expand_builtin_saveregs (void);
extern void expand_builtin_trap (void);
extern rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
-extern void expand_builtin_mem_thread_fence (enum memmodel);
/* Functions from expr.c: */
diff --git a/gcc/final.c b/gcc/final.c
index cc3a199692e..60df6fa70a6 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -3585,7 +3585,7 @@ output_addr_const (FILE *file, rtx x)
break;
case CONST_INT:
- fprint_w (file, INTVAL (x));
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
break;
case CONST:
@@ -3741,33 +3741,6 @@ sprint_ul_rev (char *s, unsigned long value)
return i;
}
-/* Write a signed HOST_WIDE_INT as decimal to a file, fast. */
-
-void
-fprint_w (FILE *f, HOST_WIDE_INT value)
-{
- /* python says: len(str(2**64)) == 20 */
- char s[20];
- int i;
-
- if (value >= 0)
- i = sprint_ul_rev (s, (unsigned long) value);
- else
- {
- /* Cast to long long to output max negative correctly! */
- i = sprint_ul_rev (s, ((unsigned long long) value) * -1);
- putc('-', f);
- }
-
- /* It's probably too small to bother with string reversal and fputs. */
- do
- {
- i--;
- putc (s[i], f);
- }
- while (i != 0);
-}
-
/* Write an unsigned long as decimal to a file, fast. */
void
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index 430ac93805c..f757423e56a 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -118,7 +118,11 @@ enum ira_region
{
IRA_REGION_ONE,
IRA_REGION_ALL,
- IRA_REGION_MIXED
+ IRA_REGION_MIXED,
+ /* This value means that there were no options -fira-region on the
+ command line and that we should choose a value depending on the
+ used -O option. */
+ IRA_REGION_AUTODETECT
};
/* The options for excess precision. */
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 167573b17b3..8f31a5fdb0e 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -13483,10 +13483,12 @@ fold_binary_loc (location_t loc,
sel[i] = i * 2 + 1;
break;
case VEC_INTERLEAVE_HIGH_EXPR:
- sel[i] = (i + nelts) / 2 + ((i & 1) ? nelts : 0);
+ sel[i] = (i + (BYTES_BIG_ENDIAN ? 0 : nelts)) / 2
+ + ((i & 1) ? nelts : 0);
break;
case VEC_INTERLEAVE_LOW_EXPR:
- sel[i] = i / 2 + ((i & 1) ? nelts : 0);
+ sel[i] = (i + (BYTES_BIG_ENDIAN ? nelts : 0)) / 2
+ + ((i & 1) ? nelts : 0);
break;
default:
gcc_unreachable ();
@@ -14157,7 +14159,8 @@ fold_checksum_tree (const_tree expr, struct md5_ctx *ctx, htab_t ht)
}
}
md5_process_bytes (expr, tree_size (expr), ctx);
- fold_checksum_tree (TREE_TYPE (expr), ctx, ht);
+ if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
+ fold_checksum_tree (TREE_TYPE (expr), ctx, ht);
if (TREE_CODE_CLASS (code) != tcc_type
&& TREE_CODE_CLASS (code) != tcc_declaration
&& code != TREE_LIST
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 01abd74f890..393f2a05076 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,105 @@
+2011-11-28 Tobias Burnus <burnus@net-b.de>
+ Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/51308
+ * symbol.c (check_conflict): Ignore BIND(C) + PARAMETER
+ conflicts for ISO_C_BINDING variables.
+ (gen_special_c_interop_ptr): Don't mark c_ptr_null/c_funptr_null
+ as SAVE.
+
+2011-11-25 Mikael Morin <mikael@gcc.gnu.org>
+
+ * trans-array.c (set_loop_bounds): Remove dead conditions.
+
+2011-11-25 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/51250
+ PR fortran/43829
+ * trans-array.c (gfc_trans_create_temp_array): Get dimension from
+ the right gfc_ss struct.
+
+2011-11-25 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/50408
+ * trans-decl.c (gfc_get_module_backend_decl): Also copy
+ ts.u.derived from the gsym if the ts.type is BT_CLASS.
+ (gfc_get_extern_function_decl): Copy also the backend_decl
+ for the symbol's ts.u.{derived,cl} from the gsym.
+ * trans-types.c (gfc_copy_dt_decls_ifequal): Directly
+ return if "from" and "to" are the same.
+
+2011-11-25 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/51302
+ * trans-stmt.c (gfc_trans_simple_do): Add a fold_convert.
+
+2011-11-24 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/51218
+ * resolve.c (pure_subroutine): If called subroutine is
+ impure, unset implicit_pure.
+ (resolve_function): Move impure check to simplify code.
+
+2011-11-19 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/51207
+ * class.c (gfc_find_derived_vtab): Mark __def_init as PARAMETER
+ and hence as TREE_READONLY; add subroutine attribute to
+ __copy_ procedure.
+
+ PR fortran/50640
+ * trans.h (GFC_DECL_PUSH_TOPLEVEL): New DECL_LANG_FLAG_7.
+ * trans-decl.c (gfc_get_symbol_decl): Mark __def_init and vtab as
+ GFC_DECL_PUSH_TOPLEVEL.
+ (gfc_generate_function_code): If GFC_DECL_PUSH_TOPLEVEL, push it there.
+ (build_function_decl): Push __copy_ procedure to the toplevel.
+
+2011-11-16 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/39427
+ PR fortran/37829
+ * decl.c (match_data_constant, match_data_constant, variable_decl,
+ gfc_match_decl_type_spec, access_attr_decl,
+ check_extended_derived_type, gfc_match_derived_decl,
+ gfc_match_derived_decl, gfc_match_derived_decl) Modified to deal
+ with DT constructors.
+ * gfortran.h (gfc_find_dt_in_generic,
+ gfc_convert_to_structure_constructor): New function prototypes.
+ * interface.c (check_interface0, check_interface1,
+ gfc_search_interface): Ignore DT constructors in generic list.
+ * match.h (gfc_match_structure_constructor): Update prototype.
+ * match.c (match_derived_type_spec): Ensure that one uses the DT
+ not the generic function.
+ * module.c (MOD_VERSION): Bump.
+ (dt_lower_string, dt_upper_string): New functions.
+ (find_use_name_n, find_use_operator, compare_true_names,
+ find_true_name, add_true_name, fix_mio_expr, load_needed,
+ read_module, write_dt_extensions, write_symbol): Changes to deal with
+ different symtree vs. sym names.
+ (create_derived_type): Create also generic procedure.
+ * parse.c (gfc_fixup_sibling_symbols): Don't regard DT and generic
+ function as the same.
+ * primary.c (gfc_convert_to_structure_constructor): New function.
+ (gfc_match_structure_constructor): Restructured; calls
+ gfc_convert_to_structure_constructor.
+ (build_actual_constructor, gfc_match_rvalue): Update for DT generic
+ functions.
+ * resolve.c (resolve_formal_arglist, resolve_structure_cons,
+ is_illegal_recursion, resolve_generic_f, resolve_variable,
+ resolve_fl_variable_derived, resolve_fl_derived0,
+ resolve_symbol): Handle DT and DT generic constructors.
+ * symbol.c (gfc_use_derived, gfc_undo_symbols,
+ gen_special_c_interop_ptr, gen_cptr_param,
+ generate_isocbinding_symbol, gfc_get_derived_super_type): Handle
+ derived-types, which are hidden in the generic type.
+ (gfc_find_dt_in_generic): New function
+ * trans-array.c (gfc_conv_array_initializer): Replace FL_PARAMETER
+ expr by actual value.
+ * trans-decl.c (gfc_get_module_backend_decl, gfc_trans_use_stmts):
+ Ensure that we use the DT and not the generic function.
+ * trans-types.c (gfc_get_derived_type): Ensure that we use the DT
+ and not the generic procedure.
+
2011-11-14 Tobias Burnus <burnus@net-b.de>
PR fortran/51073
diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c
index dc76ad158bb..bcb2d0b76bc 100644
--- a/gcc/fortran/class.c
+++ b/gcc/fortran/class.c
@@ -522,7 +522,7 @@ gfc_find_derived_vtab (gfc_symbol *derived)
def_init->attr.target = 1;
def_init->attr.save = SAVE_IMPLICIT;
def_init->attr.access = ACCESS_PUBLIC;
- def_init->attr.flavor = FL_VARIABLE;
+ def_init->attr.flavor = FL_PARAMETER;
gfc_set_sym_referenced (def_init);
def_init->ts.type = BT_DERIVED;
def_init->ts.u.derived = derived;
@@ -552,6 +552,7 @@ gfc_find_derived_vtab (gfc_symbol *derived)
gfc_get_symbol (name, sub_ns, &copy);
sub_ns->proc_name = copy;
copy->attr.flavor = FL_PROCEDURE;
+ copy->attr.subroutine = 1;
copy->attr.if_source = IFSRC_DECL;
if (ns->proc_name->attr.flavor == FL_MODULE)
copy->module = ns->proc_name->name;
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 2dd38b9485e..3e553a38143 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -323,7 +323,7 @@ static match
match_data_constant (gfc_expr **result)
{
char name[GFC_MAX_SYMBOL_LEN + 1];
- gfc_symbol *sym;
+ gfc_symbol *sym, *dt_sym = NULL;
gfc_expr *expr;
match m;
locus old_loc;
@@ -366,15 +366,19 @@ match_data_constant (gfc_expr **result)
if (gfc_find_symbol (name, NULL, 1, &sym))
return MATCH_ERROR;
+ if (sym && sym->attr.generic)
+ dt_sym = gfc_find_dt_in_generic (sym);
+
if (sym == NULL
- || (sym->attr.flavor != FL_PARAMETER && sym->attr.flavor != FL_DERIVED))
+ || (sym->attr.flavor != FL_PARAMETER
+ && (!dt_sym || dt_sym->attr.flavor != FL_DERIVED)))
{
gfc_error ("Symbol '%s' must be a PARAMETER in DATA statement at %C",
name);
return MATCH_ERROR;
}
- else if (sym->attr.flavor == FL_DERIVED)
- return gfc_match_structure_constructor (sym, result, false);
+ else if (dt_sym && dt_sym->attr.flavor == FL_DERIVED)
+ return gfc_match_structure_constructor (dt_sym, result);
/* Check to see if the value is an initialization array expression. */
if (sym->value->expr_type == EXPR_ARRAY)
@@ -1954,10 +1958,10 @@ variable_decl (int elem)
st = gfc_find_symtree (gfc_current_ns->sym_root, current_ts.u.derived->name);
if (!(current_ts.u.derived->attr.imported
&& st != NULL
- && st->n.sym == current_ts.u.derived)
+ && gfc_find_dt_in_generic (st->n.sym) == current_ts.u.derived)
&& !gfc_current_ns->has_import_set)
{
- gfc_error ("the type of '%s' at %C has not been declared within the "
+ gfc_error ("The type of '%s' at %C has not been declared within the "
"interface", name);
m = MATCH_ERROR;
goto cleanup;
@@ -2501,10 +2505,11 @@ match
gfc_match_decl_type_spec (gfc_typespec *ts, int implicit_flag)
{
char name[GFC_MAX_SYMBOL_LEN + 1];
- gfc_symbol *sym;
+ gfc_symbol *sym, *dt_sym;
match m;
char c;
bool seen_deferred_kind, matched_type;
+ const char *dt_name;
/* A belt and braces check that the typespec is correctly being treated
as a deferred characteristic association. */
@@ -2668,40 +2673,96 @@ gfc_match_decl_type_spec (gfc_typespec *ts, int implicit_flag)
ts->u.derived = NULL;
if (gfc_current_state () != COMP_INTERFACE
&& !gfc_find_symbol (name, NULL, 1, &sym) && sym)
- ts->u.derived = sym;
+ {
+ sym = gfc_find_dt_in_generic (sym);
+ ts->u.derived = sym;
+ }
return MATCH_YES;
}
/* Search for the name but allow the components to be defined later. If
type = -1, this typespec has been seen in a function declaration but
- the type could not be accessed at that point. */
+ the type could not be accessed at that point. The actual derived type is
+ stored in a symtree with the first letter of the name captialized; the
+ symtree with the all lower-case name contains the associated
+ generic function. */
+ dt_name = gfc_get_string ("%c%s",
+ (char) TOUPPER ((unsigned char) name[0]),
+ (const char*)&name[1]);
sym = NULL;
- if (ts->kind != -1 && gfc_get_ha_symbol (name, &sym))
+ dt_sym = NULL;
+ if (ts->kind != -1)
{
- gfc_error ("Type name '%s' at %C is ambiguous", name);
- return MATCH_ERROR;
+ gfc_get_ha_symbol (name, &sym);
+ if (sym->generic && gfc_find_symbol (dt_name, NULL, 0, &dt_sym))
+ {
+ gfc_error ("Type name '%s' at %C is ambiguous", name);
+ return MATCH_ERROR;
+ }
+ if (sym->generic && !dt_sym)
+ dt_sym = gfc_find_dt_in_generic (sym);
}
else if (ts->kind == -1)
{
int iface = gfc_state_stack->previous->state != COMP_INTERFACE
|| gfc_current_ns->has_import_set;
- if (gfc_find_symbol (name, NULL, iface, &sym))
+ gfc_find_symbol (name, NULL, iface, &sym);
+ if (sym && sym->generic && gfc_find_symbol (dt_name, NULL, 1, &dt_sym))
{
gfc_error ("Type name '%s' at %C is ambiguous", name);
return MATCH_ERROR;
}
+ if (sym && sym->generic && !dt_sym)
+ dt_sym = gfc_find_dt_in_generic (sym);
ts->kind = 0;
if (sym == NULL)
return MATCH_NO;
}
- if (sym->attr.flavor != FL_DERIVED
- && gfc_add_flavor (&sym->attr, FL_DERIVED, sym->name, NULL) == FAILURE)
- return MATCH_ERROR;
+ if ((sym->attr.flavor != FL_UNKNOWN
+ && !(sym->attr.flavor == FL_PROCEDURE && sym->attr.generic))
+ || sym->attr.subroutine)
+ {
+ gfc_error ("Type name '%s' at %C conflicts with previously declared "
+ "entity at %L, which has the same name", name,
+ &sym->declared_at);
+ return MATCH_ERROR;
+ }
gfc_set_sym_referenced (sym);
- ts->u.derived = sym;
+ if (!sym->attr.generic
+ && gfc_add_generic (&sym->attr, sym->name, NULL) == FAILURE)
+ return MATCH_ERROR;
+
+ if (!sym->attr.function
+ && gfc_add_function (&sym->attr, sym->name, NULL) == FAILURE)
+ return MATCH_ERROR;
+
+ if (!dt_sym)
+ {
+ gfc_interface *intr, *head;
+
+ /* Use upper case to save the actual derived-type symbol. */
+ gfc_get_symbol (dt_name, NULL, &dt_sym);
+ dt_sym->name = gfc_get_string (sym->name);
+ head = sym->generic;
+ intr = gfc_get_interface ();
+ intr->sym = dt_sym;
+ intr->where = gfc_current_locus;
+ intr->next = head;
+ sym->generic = intr;
+ sym->attr.if_source = IFSRC_DECL;
+ }
+
+ gfc_set_sym_referenced (dt_sym);
+
+ if (dt_sym->attr.flavor != FL_DERIVED
+ && gfc_add_flavor (&dt_sym->attr, FL_DERIVED, sym->name, NULL)
+ == FAILURE)
+ return MATCH_ERROR;
+
+ ts->u.derived = dt_sym;
return MATCH_YES;
@@ -3053,6 +3114,20 @@ gfc_match_import (void)
sym->refs++;
sym->attr.imported = 1;
+ if (sym->attr.generic && (sym = gfc_find_dt_in_generic (sym)))
+ {
+ /* The actual derived type is stored in a symtree with the first
+ letter of the name captialized; the symtree with the all
+ lower-case name contains the associated generic function. */
+ st = gfc_new_symtree (&gfc_current_ns->sym_root,
+ gfc_get_string ("%c%s",
+ (char) TOUPPER ((unsigned char) sym->name[0]),
+ &sym->name[1]));
+ st->n.sym = sym;
+ sym->refs++;
+ sym->attr.imported = 1;
+ }
+
goto next_item;
case MATCH_NO:
@@ -6475,7 +6550,7 @@ access_attr_decl (gfc_statement st)
char name[GFC_MAX_SYMBOL_LEN + 1];
interface_type type;
gfc_user_op *uop;
- gfc_symbol *sym;
+ gfc_symbol *sym, *dt_sym;
gfc_intrinsic_op op;
match m;
@@ -6505,6 +6580,13 @@ access_attr_decl (gfc_statement st)
sym->name, NULL) == FAILURE)
return MATCH_ERROR;
+ if (sym->attr.generic && (dt_sym = gfc_find_dt_in_generic (sym))
+ && gfc_add_access (&dt_sym->attr,
+ (st == ST_PUBLIC) ? ACCESS_PUBLIC
+ : ACCESS_PRIVATE,
+ sym->name, NULL) == FAILURE)
+ return MATCH_ERROR;
+
break;
case INTERFACE_INTRINSIC_OP:
@@ -7175,6 +7257,8 @@ check_extended_derived_type (char *name)
return NULL;
}
+ extended = gfc_find_dt_in_generic (extended);
+
if (extended->attr.flavor != FL_DERIVED)
{
gfc_error ("'%s' in EXTENDS expression at %C is not a "
@@ -7277,11 +7361,12 @@ gfc_match_derived_decl (void)
char name[GFC_MAX_SYMBOL_LEN + 1];
char parent[GFC_MAX_SYMBOL_LEN + 1];
symbol_attribute attr;
- gfc_symbol *sym;
+ gfc_symbol *sym, *gensym;
gfc_symbol *extended;
match m;
match is_type_attr_spec = MATCH_NO;
bool seen_attr = false;
+ gfc_interface *intr = NULL, *head;
if (gfc_current_state () == COMP_DERIVED)
return MATCH_NO;
@@ -7327,16 +7412,50 @@ gfc_match_derived_decl (void)
return MATCH_ERROR;
}
- if (gfc_get_symbol (name, NULL, &sym))
+ if (gfc_get_symbol (name, NULL, &gensym))
return MATCH_ERROR;
- if (sym->ts.type != BT_UNKNOWN)
+ if (!gensym->attr.generic && gensym->ts.type != BT_UNKNOWN)
{
gfc_error ("Derived type name '%s' at %C already has a basic type "
- "of %s", sym->name, gfc_typename (&sym->ts));
+ "of %s", gensym->name, gfc_typename (&gensym->ts));
+ return MATCH_ERROR;
+ }
+
+ if (!gensym->attr.generic
+ && gfc_add_generic (&gensym->attr, gensym->name, NULL) == FAILURE)
+ return MATCH_ERROR;
+
+ if (!gensym->attr.function
+ && gfc_add_function (&gensym->attr, gensym->name, NULL) == FAILURE)
+ return MATCH_ERROR;
+
+ sym = gfc_find_dt_in_generic (gensym);
+
+ if (sym && (sym->components != NULL || sym->attr.zero_comp))
+ {
+ gfc_error ("Derived type definition of '%s' at %C has already been "
+ "defined", sym->name);
return MATCH_ERROR;
}
+ if (!sym)
+ {
+ /* Use upper case to save the actual derived-type symbol. */
+ gfc_get_symbol (gfc_get_string ("%c%s",
+ (char) TOUPPER ((unsigned char) gensym->name[0]),
+ &gensym->name[1]), NULL, &sym);
+ sym->name = gfc_get_string (gensym->name);
+ head = gensym->generic;
+ intr = gfc_get_interface ();
+ intr->sym = sym;
+ intr->where = gfc_current_locus;
+ intr->sym->declared_at = gfc_current_locus;
+ intr->next = head;
+ gensym->generic = intr;
+ gensym->attr.if_source = IFSRC_DECL;
+ }
+
/* The symbol may already have the derived attribute without the
components. The ways this can happen is via a function
definition, an INTRINSIC statement or a subtype in another
@@ -7346,16 +7465,18 @@ gfc_match_derived_decl (void)
&& gfc_add_flavor (&sym->attr, FL_DERIVED, sym->name, NULL) == FAILURE)
return MATCH_ERROR;
- if (sym->components != NULL || sym->attr.zero_comp)
- {
- gfc_error ("Derived type definition of '%s' at %C has already been "
- "defined", sym->name);
- return MATCH_ERROR;
- }
-
if (attr.access != ACCESS_UNKNOWN
&& gfc_add_access (&sym->attr, attr.access, sym->name, NULL) == FAILURE)
return MATCH_ERROR;
+ else if (sym->attr.access == ACCESS_UNKNOWN
+ && gensym->attr.access != ACCESS_UNKNOWN
+ && gfc_add_access (&sym->attr, gensym->attr.access, sym->name, NULL)
+ == FAILURE)
+ return MATCH_ERROR;
+
+ if (sym->attr.access != ACCESS_UNKNOWN
+ && gensym->attr.access == ACCESS_UNKNOWN)
+ gensym->attr.access = sym->attr.access;
/* See if the derived type was labeled as bind(c). */
if (attr.is_bind_c != 0)
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 17ebd58e50f..372c056d3d1 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2630,6 +2630,7 @@ gfc_try gfc_check_symbol_typed (gfc_symbol*, gfc_namespace*, bool, locus);
gfc_namespace* gfc_find_proc_namespace (gfc_namespace*);
bool gfc_is_associate_pointer (gfc_symbol*);
+gfc_symbol * gfc_find_dt_in_generic (gfc_symbol *);
/* intrinsic.c -- true if working in an init-expr, false otherwise. */
extern bool gfc_init_expr_flag;
@@ -2874,6 +2875,9 @@ match gfc_match_rvalue (gfc_expr **);
match gfc_match_varspec (gfc_expr*, int, bool, bool);
int gfc_check_digit (char, int);
bool gfc_is_function_return_value (gfc_symbol *, gfc_namespace *);
+gfc_try gfc_convert_to_structure_constructor (gfc_expr *, gfc_symbol *,
+ gfc_expr **,
+ gfc_actual_arglist **, bool);
/* trans.c */
void gfc_generate_code (gfc_namespace *);
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index 90d98c759dd..6d2acce378a 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -1262,8 +1262,9 @@ check_interface0 (gfc_interface *p, const char *interface_name)
{
/* Make sure all symbols in the interface have been defined as
functions or subroutines. */
- if ((!p->sym->attr.function && !p->sym->attr.subroutine)
- || !p->sym->attr.if_source)
+ if (((!p->sym->attr.function && !p->sym->attr.subroutine)
+ || !p->sym->attr.if_source)
+ && p->sym->attr.flavor != FL_DERIVED)
{
if (p->sym->attr.external)
gfc_error ("Procedure '%s' in %s at %L has no explicit interface",
@@ -1276,11 +1277,18 @@ check_interface0 (gfc_interface *p, const char *interface_name)
}
/* Verify that procedures are either all SUBROUTINEs or all FUNCTIONs. */
- if ((psave->sym->attr.function && !p->sym->attr.function)
+ if ((psave->sym->attr.function && !p->sym->attr.function
+ && p->sym->attr.flavor != FL_DERIVED)
|| (psave->sym->attr.subroutine && !p->sym->attr.subroutine))
{
- gfc_error ("In %s at %L procedures must be either all SUBROUTINEs"
- " or all FUNCTIONs", interface_name, &p->sym->declared_at);
+ if (p->sym->attr.flavor != FL_DERIVED)
+ gfc_error ("In %s at %L procedures must be either all SUBROUTINEs"
+ " or all FUNCTIONs", interface_name,
+ &p->sym->declared_at);
+ else
+ gfc_error ("In %s at %L procedures must be all FUNCTIONs as the "
+ "generic name is also the name of a derived type",
+ interface_name, &p->sym->declared_at);
return 1;
}
@@ -1336,8 +1344,10 @@ check_interface1 (gfc_interface *p, gfc_interface *q0,
if (p->sym->name == q->sym->name && p->sym->module == q->sym->module)
continue;
- if (gfc_compare_interfaces (p->sym, q->sym, q->sym->name, generic_flag,
- 0, NULL, 0))
+ if (p->sym->attr.flavor != FL_DERIVED
+ && q->sym->attr.flavor != FL_DERIVED
+ && gfc_compare_interfaces (p->sym, q->sym, q->sym->name,
+ generic_flag, 0, NULL, 0))
{
if (referenced)
gfc_error ("Ambiguous interfaces '%s' and '%s' in %s at %L",
@@ -3019,6 +3029,8 @@ gfc_search_interface (gfc_interface *intr, int sub_flag,
for (; intr; intr = intr->next)
{
+ if (intr->sym->attr.flavor == FL_DERIVED)
+ continue;
if (sub_flag && intr->sym->attr.function)
continue;
if (!sub_flag && intr->sym->attr.subroutine)
diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c
index 4ea98b61017..fbafe82cc66 100644
--- a/gcc/fortran/match.c
+++ b/gcc/fortran/match.c
@@ -1920,6 +1920,9 @@ match_derived_type_spec (gfc_typespec *ts)
gfc_find_symbol (name, NULL, 1, &derived);
+ if (derived && derived->attr.flavor == FL_PROCEDURE && derived->attr.generic)
+ derived = gfc_find_dt_in_generic (derived);
+
if (derived && derived->attr.flavor == FL_DERIVED)
{
ts->type = BT_DERIVED;
diff --git a/gcc/fortran/match.h b/gcc/fortran/match.h
index 0d841044b98..df18074c58a 100644
--- a/gcc/fortran/match.h
+++ b/gcc/fortran/match.h
@@ -206,7 +206,7 @@ match gfc_match_bind_c (gfc_symbol *, bool);
match gfc_get_type_attr_spec (symbol_attribute *, char*);
/* primary.c. */
-match gfc_match_structure_constructor (gfc_symbol *, gfc_expr **, bool);
+match gfc_match_structure_constructor (gfc_symbol *, gfc_expr **);
match gfc_match_variable (gfc_expr **, int);
match gfc_match_equiv_variable (gfc_expr **);
match gfc_match_actual_arglist (int, gfc_actual_arglist **);
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index 62f759876d3..7c28e8bb97c 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -80,7 +80,7 @@ along with GCC; see the file COPYING3. If not see
/* Don't put any single quote (') in MOD_VERSION,
if yout want it to be recognized. */
-#define MOD_VERSION "7"
+#define MOD_VERSION "8"
/* Structure that describes a position within a module file. */
@@ -429,6 +429,34 @@ resolve_fixups (fixup_t *f, void *gp)
}
+/* Convert a string such that it starts with a lower-case character. Used
+ to convert the symtree name of a derived-type to the symbol name or to
+ the name of the associated generic function. */
+
+const char *
+dt_lower_string (const char *name)
+{
+ if (name[0] != (char) TOLOWER ((unsigned char) name[0]))
+ return gfc_get_string ("%c%s", (char) TOLOWER ((unsigned char) name[0]),
+ &name[1]);
+ return gfc_get_string (name);
+}
+
+
+/* Convert a string such that it starts with an upper-case character. Used to
+ return the symtree-name for a derived type; the symbol name itself and the
+ symtree/symbol name of the associated generic function start with a lower-
+ case character. */
+
+const char *
+dt_upper_string (const char *name)
+{
+ if (name[0] != (char) TOUPPER ((unsigned char) name[0]))
+ return gfc_get_string ("%c%s", (char) TOUPPER ((unsigned char) name[0]),
+ &name[1]);
+ return gfc_get_string (name);
+}
+
/* Call here during module reading when we know what pointer to
associate with an integer. Any fixups that exist are resolved at
this time. */
@@ -699,12 +727,18 @@ static const char *
find_use_name_n (const char *name, int *inst, bool interface)
{
gfc_use_rename *u;
+ const char *low_name = NULL;
int i;
+ /* For derived types. */
+ if (name[0] != (char) TOLOWER ((unsigned char) name[0]))
+ low_name = dt_lower_string (name);
+
i = 0;
for (u = gfc_rename_list; u; u = u->next)
{
- if (strcmp (u->use_name, name) != 0
+ if ((!low_name && strcmp (u->use_name, name) != 0)
+ || (low_name && strcmp (u->use_name, low_name) != 0)
|| (u->op == INTRINSIC_USER && !interface)
|| (u->op != INTRINSIC_USER && interface))
continue;
@@ -723,6 +757,13 @@ find_use_name_n (const char *name, int *inst, bool interface)
u->found = 1;
+ if (low_name)
+ {
+ if (u->local_name[0] == '\0')
+ return name;
+ return dt_upper_string (u->local_name);
+ }
+
return (u->local_name[0] != '\0') ? u->local_name : name;
}
@@ -780,6 +821,7 @@ find_use_operator (gfc_intrinsic_op op)
typedef struct true_name
{
BBT_HEADER (true_name);
+ const char *name;
gfc_symbol *sym;
}
true_name;
@@ -803,7 +845,7 @@ compare_true_names (void *_t1, void *_t2)
if (c != 0)
return c;
- return strcmp (t1->sym->name, t2->sym->name);
+ return strcmp (t1->name, t2->name);
}
@@ -817,7 +859,7 @@ find_true_name (const char *name, const char *module)
gfc_symbol sym;
int c;
- sym.name = gfc_get_string (name);
+ t.name = gfc_get_string (name);
if (module != NULL)
sym.module = gfc_get_string (module);
else
@@ -847,6 +889,10 @@ add_true_name (gfc_symbol *sym)
t = XCNEW (true_name);
t->sym = sym;
+ if (sym->attr.flavor == FL_DERIVED)
+ t->name = dt_upper_string (sym->name);
+ else
+ t->name = sym->name;
gfc_insert_bbt (&true_name_root, t, compare_true_names);
}
@@ -858,13 +904,19 @@ add_true_name (gfc_symbol *sym)
static void
build_tnt (gfc_symtree *st)
{
+ const char *name;
if (st == NULL)
return;
build_tnt (st->left);
build_tnt (st->right);
- if (find_true_name (st->n.sym->name, st->n.sym->module) != NULL)
+ if (st->n.sym->attr.flavor == FL_DERIVED)
+ name = dt_upper_string (st->n.sym->name);
+ else
+ name = st->n.sym->name;
+
+ if (find_true_name (name, st->n.sym->module) != NULL)
return;
add_true_name (st->n.sym);
@@ -2986,8 +3038,12 @@ fix_mio_expr (gfc_expr *e)
namespace to see if the required, non-contained symbol is available
yet. If so, the latter should be written. */
if (e->symtree->n.sym && check_unique_name (e->symtree->name))
- ns_st = gfc_find_symtree (gfc_current_ns->sym_root,
- e->symtree->n.sym->name);
+ {
+ const char *name = e->symtree->n.sym->name;
+ if (e->symtree->n.sym->attr.flavor == FL_DERIVED)
+ name = dt_upper_string (name);
+ ns_st = gfc_find_symtree (gfc_current_ns->sym_root, name);
+ }
/* On the other hand, if the existing symbol is the module name or the
new symbol is a dummy argument, do not do the promotion. */
@@ -4205,6 +4261,7 @@ load_needed (pointer_info *p)
1, &ns->proc_name);
sym = gfc_new_symbol (p->u.rsym.true_name, ns);
+ sym->name = dt_lower_string (p->u.rsym.true_name);
sym->module = gfc_get_string (p->u.rsym.module);
strcpy (sym->binding_label, p->u.rsym.binding_label);
@@ -4497,6 +4554,7 @@ read_module (void)
{
info->u.rsym.sym = gfc_new_symbol (info->u.rsym.true_name,
gfc_current_ns);
+ info->u.rsym.sym->name = dt_lower_string (info->u.rsym.true_name);
sym = info->u.rsym.sym;
sym->module = gfc_get_string (info->u.rsym.module);
@@ -4835,7 +4893,7 @@ write_dt_extensions (gfc_symtree *st)
return;
mio_lparen ();
- mio_pool_string (&st->n.sym->name);
+ mio_pool_string (&st->name);
if (st->n.sym->module != NULL)
mio_pool_string (&st->n.sym->module);
else
@@ -4870,7 +4928,15 @@ write_symbol (int n, gfc_symbol *sym)
gfc_internal_error ("write_symbol(): bad module symbol '%s'", sym->name);
mio_integer (&n);
- mio_pool_string (&sym->name);
+
+ if (sym->attr.flavor == FL_DERIVED)
+ {
+ const char *name;
+ name = dt_upper_string (sym->name);
+ mio_pool_string (&name);
+ }
+ else
+ mio_pool_string (&sym->name);
mio_pool_string (&sym->module);
if (sym->attr.is_bind_c || sym->attr.is_iso_c)
@@ -5566,7 +5632,8 @@ create_derived_type (const char *name, const char *modname,
intmod_id module, int id)
{
gfc_symtree *tmp_symtree;
- gfc_symbol *sym;
+ gfc_symbol *sym, *dt_sym;
+ gfc_interface *intr, *head;
tmp_symtree = gfc_find_symtree (gfc_current_ns->sym_root, name);
if (tmp_symtree != NULL)
@@ -5579,18 +5646,35 @@ create_derived_type (const char *name, const char *modname,
gfc_get_sym_tree (name, gfc_current_ns, &tmp_symtree, false);
sym = tmp_symtree->n.sym;
-
sym->module = gfc_get_string (modname);
sym->from_intmod = module;
sym->intmod_sym_id = id;
- sym->attr.flavor = FL_DERIVED;
- sym->attr.private_comp = 1;
- sym->attr.zero_comp = 1;
- sym->attr.use_assoc = 1;
+ sym->attr.flavor = FL_PROCEDURE;
+ sym->attr.function = 1;
+ sym->attr.generic = 1;
+
+ gfc_get_sym_tree (dt_upper_string (sym->name),
+ gfc_current_ns, &tmp_symtree, false);
+ dt_sym = tmp_symtree->n.sym;
+ dt_sym->name = gfc_get_string (sym->name);
+ dt_sym->attr.flavor = FL_DERIVED;
+ dt_sym->attr.private_comp = 1;
+ dt_sym->attr.zero_comp = 1;
+ dt_sym->attr.use_assoc = 1;
+ dt_sym->module = gfc_get_string (modname);
+ dt_sym->from_intmod = module;
+ dt_sym->intmod_sym_id = id;
+
+ head = sym->generic;
+ intr = gfc_get_interface ();
+ intr->sym = dt_sym;
+ intr->where = gfc_current_locus;
+ intr->next = head;
+ sym->generic = intr;
+ sym->attr.if_source = IFSRC_DECL;
}
-
/* USE the ISO_FORTRAN_ENV intrinsic module. */
static void
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index 24d8960d06b..7d91645207b 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -3881,6 +3881,12 @@ gfc_fixup_sibling_symbols (gfc_symbol *sym, gfc_namespace *siblings)
if (!st || (st->n.sym->attr.dummy && ns == st->n.sym->ns))
goto fixup_contained;
+ if ((st->n.sym->attr.flavor == FL_DERIVED
+ && sym->attr.generic && sym->attr.function)
+ ||(sym->attr.flavor == FL_DERIVED
+ && st->n.sym->attr.generic && st->n.sym->attr.function))
+ goto fixup_contained;
+
old_sym = st->n.sym;
if (old_sym->ns == ns
&& !old_sym->attr.contained
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index 23dc0b66400..0f67ec78282 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -2315,171 +2315,162 @@ build_actual_constructor (gfc_structure_ctor_component **comp_head,
return SUCCESS;
}
-match
-gfc_match_structure_constructor (gfc_symbol *sym, gfc_expr **result,
- bool parent)
+
+gfc_try
+gfc_convert_to_structure_constructor (gfc_expr *e, gfc_symbol *sym, gfc_expr **cexpr,
+ gfc_actual_arglist **arglist,
+ bool parent)
{
+ gfc_actual_arglist *actual;
gfc_structure_ctor_component *comp_tail, *comp_head, *comp_iter;
gfc_constructor_base ctor_head = NULL;
gfc_component *comp; /* Is set NULL when named component is first seen */
- gfc_expr *e;
- locus where;
- match m;
const char* last_name = NULL;
+ locus old_locus;
+ gfc_expr *expr;
- comp_tail = comp_head = NULL;
-
- if (!parent && gfc_match_char ('(') != MATCH_YES)
- goto syntax;
-
- where = gfc_current_locus;
+ expr = parent ? *cexpr : e;
+ old_locus = gfc_current_locus;
+ if (parent)
+ ; /* gfc_current_locus = *arglist->expr ? ->where;*/
+ else
+ gfc_current_locus = expr->where;
- gfc_find_component (sym, NULL, false, true);
+ comp_tail = comp_head = NULL;
- /* Check that we're not about to construct an ABSTRACT type. */
if (!parent && sym->attr.abstract)
{
- gfc_error ("Can't construct ABSTRACT type '%s' at %C", sym->name);
- return MATCH_ERROR;
+ gfc_error ("Can't construct ABSTRACT type '%s' at %L",
+ sym->name, &expr->where);
+ goto cleanup;
}
- /* Match the component list and store it in a list together with the
- corresponding component names. Check for empty argument list first. */
- if (gfc_match_char (')') != MATCH_YES)
+ comp = sym->components;
+ actual = parent ? *arglist : expr->value.function.actual;
+ for ( ; actual; )
{
- comp = sym->components;
- do
- {
- gfc_component *this_comp = NULL;
-
- if (comp == sym->components && sym->attr.extension
- && comp->ts.type == BT_DERIVED
- && comp->ts.u.derived->attr.zero_comp)
- /* Skip empty parents. */
- comp = comp->next;
+ gfc_component *this_comp = NULL;
- if (!comp_head)
- comp_tail = comp_head = gfc_get_structure_ctor_component ();
- else
- {
- comp_tail->next = gfc_get_structure_ctor_component ();
- comp_tail = comp_tail->next;
- }
- comp_tail->name = XCNEWVEC (char, GFC_MAX_SYMBOL_LEN + 1);
- comp_tail->val = NULL;
- comp_tail->where = gfc_current_locus;
+ if (!comp_head)
+ comp_tail = comp_head = gfc_get_structure_ctor_component ();
+ else
+ {
+ comp_tail->next = gfc_get_structure_ctor_component ();
+ comp_tail = comp_tail->next;
+ }
+ if (actual->name)
+ {
+ if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: Structure"
+ " constructor with named arguments at %C")
+ == FAILURE)
+ goto cleanup;
- /* Try matching a component name. */
- if (gfc_match_name (comp_tail->name) == MATCH_YES
- && gfc_match_char ('=') == MATCH_YES)
+ comp_tail->name = xstrdup (actual->name);
+ last_name = comp_tail->name;
+ comp = NULL;
+ }
+ else
+ {
+ /* Components without name are not allowed after the first named
+ component initializer! */
+ if (!comp)
{
- if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: Structure"
- " constructor with named arguments at %C")
- == FAILURE)
- goto cleanup;
-
- last_name = comp_tail->name;
- comp = NULL;
+ if (last_name)
+ gfc_error ("Component initializer without name after component"
+ " named %s at %L!", last_name,
+ actual->expr ? &actual->expr->where
+ : &gfc_current_locus);
+ else
+ gfc_error ("Too many components in structure constructor at "
+ "%L!", actual->expr ? &actual->expr->where
+ : &gfc_current_locus);
+ goto cleanup;
}
- else
- {
- /* Components without name are not allowed after the first named
- component initializer! */
- if (!comp)
- {
- if (last_name)
- gfc_error ("Component initializer without name after"
- " component named %s at %C!", last_name);
- else if (!parent)
- gfc_error ("Too many components in structure constructor at"
- " %C!");
- goto cleanup;
- }
- gfc_current_locus = comp_tail->where;
- strncpy (comp_tail->name, comp->name, GFC_MAX_SYMBOL_LEN + 1);
- }
+ comp_tail->name = xstrdup (comp->name);
+ }
- /* Find the current component in the structure definition and check
+ /* Find the current component in the structure definition and check
its access is not private. */
- if (comp)
- this_comp = gfc_find_component (sym, comp->name, false, false);
- else
- {
- this_comp = gfc_find_component (sym,
- (const char *)comp_tail->name,
- false, false);
- comp = NULL; /* Reset needed! */
- }
-
- /* Here we can check if a component name is given which does not
- correspond to any component of the defined structure. */
- if (!this_comp)
- goto cleanup;
+ if (comp)
+ this_comp = gfc_find_component (sym, comp->name, false, false);
+ else
+ {
+ this_comp = gfc_find_component (sym, (const char *)comp_tail->name,
+ false, false);
+ comp = NULL; /* Reset needed! */
+ }
- /* Check if this component is already given a value. */
- for (comp_iter = comp_head; comp_iter != comp_tail;
- comp_iter = comp_iter->next)
- {
- gcc_assert (comp_iter);
- if (!strcmp (comp_iter->name, comp_tail->name))
- {
- gfc_error ("Component '%s' is initialized twice in the"
- " structure constructor at %C!", comp_tail->name);
- goto cleanup;
- }
- }
+ /* Here we can check if a component name is given which does not
+ correspond to any component of the defined structure. */
+ if (!this_comp)
+ goto cleanup;
- /* Match the current initializer expression. */
- if (this_comp->attr.proc_pointer)
- gfc_matching_procptr_assignment = 1;
- m = gfc_match_expr (&comp_tail->val);
- gfc_matching_procptr_assignment = 0;
- if (m == MATCH_NO)
- goto syntax;
- if (m == MATCH_ERROR)
- goto cleanup;
+ comp_tail->val = actual->expr;
+ if (actual->expr != NULL)
+ comp_tail->where = actual->expr->where;
+ actual->expr = NULL;
- /* F2008, R457/C725, for PURE C1283. */
- if (this_comp->attr.pointer && gfc_is_coindexed (comp_tail->val))
+ /* Check if this component is already given a value. */
+ for (comp_iter = comp_head; comp_iter != comp_tail;
+ comp_iter = comp_iter->next)
+ {
+ gcc_assert (comp_iter);
+ if (!strcmp (comp_iter->name, comp_tail->name))
{
- gfc_error ("Coindexed expression to pointer component '%s' in "
- "structure constructor at %C!", comp_tail->name);
+ gfc_error ("Component '%s' is initialized twice in the structure"
+ " constructor at %L!", comp_tail->name,
+ comp_tail->val ? &comp_tail->where
+ : &gfc_current_locus);
goto cleanup;
- }
+ }
+ }
+ /* F2008, R457/C725, for PURE C1283. */
+ if (this_comp->attr.pointer && comp_tail->val
+ && gfc_is_coindexed (comp_tail->val))
+ {
+ gfc_error ("Coindexed expression to pointer component '%s' in "
+ "structure constructor at %L!", comp_tail->name,
+ &comp_tail->where);
+ goto cleanup;
+ }
- /* If not explicitly a parent constructor, gather up the components
- and build one. */
- if (comp && comp == sym->components
- && sym->attr.extension
- && (comp_tail->val->ts.type != BT_DERIVED
- ||
- comp_tail->val->ts.u.derived != this_comp->ts.u.derived))
- {
- gfc_current_locus = where;
- gfc_free_expr (comp_tail->val);
- comp_tail->val = NULL;
+ /* If not explicitly a parent constructor, gather up the components
+ and build one. */
+ if (comp && comp == sym->components
+ && sym->attr.extension
+ && comp_tail->val
+ && (comp_tail->val->ts.type != BT_DERIVED
+ ||
+ comp_tail->val->ts.u.derived != this_comp->ts.u.derived))
+ {
+ gfc_try m;
+ gfc_actual_arglist *arg_null = NULL;
- m = gfc_match_structure_constructor (comp->ts.u.derived,
- &comp_tail->val, true);
- if (m == MATCH_NO)
- goto syntax;
- if (m == MATCH_ERROR)
- goto cleanup;
- }
+ actual->expr = comp_tail->val;
+ comp_tail->val = NULL;
- if (comp)
- comp = comp->next;
+ m = gfc_convert_to_structure_constructor (NULL,
+ comp->ts.u.derived, &comp_tail->val,
+ comp->ts.u.derived->attr.zero_comp
+ ? &arg_null : &actual, true);
+ if (m == FAILURE)
+ goto cleanup;
- if (parent && !comp)
- break;
- }
+ if (comp->ts.u.derived->attr.zero_comp)
+ {
+ comp = comp->next;
+ continue;
+ }
+ }
- while (gfc_match_char (',') == MATCH_YES);
+ if (comp)
+ comp = comp->next;
+ if (parent && !comp)
+ break;
- if (!parent && gfc_match_char (')') != MATCH_YES)
- goto syntax;
+ actual = actual->next;
}
if (build_actual_constructor (&comp_head, &ctor_head, sym) == FAILURE)
@@ -2488,9 +2479,8 @@ gfc_match_structure_constructor (gfc_symbol *sym, gfc_expr **result,
/* No component should be left, as this should have caused an error in the
loop constructing the component-list (name that does not correspond to any
component in the structure definition). */
- if (comp_head)
+ if (comp_head && sym->attr.extension)
{
- gcc_assert (sym->attr.extension);
for (comp_iter = comp_head; comp_iter; comp_iter = comp_iter->next)
{
gfc_error ("component '%s' at %L has already been set by a "
@@ -2499,18 +2489,33 @@ gfc_match_structure_constructor (gfc_symbol *sym, gfc_expr **result,
}
goto cleanup;
}
+ else
+ gcc_assert (!comp_head);
- e = gfc_get_structure_constructor_expr (BT_DERIVED, 0, &where);
- e->ts.u.derived = sym;
- e->value.constructor = ctor_head;
+ if (parent)
+ {
+ expr = gfc_get_structure_constructor_expr (BT_DERIVED, 0, &gfc_current_locus);
+ expr->ts.u.derived = sym;
+ expr->value.constructor = ctor_head;
+ *cexpr = expr;
+ }
+ else
+ {
+ expr->ts.u.derived = sym;
+ expr->ts.kind = 0;
+ expr->ts.type = BT_DERIVED;
+ expr->value.constructor = ctor_head;
+ expr->expr_type = EXPR_STRUCTURE;
+ }
- *result = e;
- return MATCH_YES;
+ gfc_current_locus = old_locus;
+ if (parent)
+ *arglist = actual;
+ return SUCCESS;
-syntax:
- gfc_error ("Syntax error in structure constructor at %C");
+ cleanup:
+ gfc_current_locus = old_locus;
-cleanup:
for (comp_iter = comp_head; comp_iter; )
{
gfc_structure_ctor_component *next = comp_iter->next;
@@ -2518,7 +2523,45 @@ cleanup:
comp_iter = next;
}
gfc_constructor_free (ctor_head);
- return MATCH_ERROR;
+
+ return FAILURE;
+}
+
+
+match
+gfc_match_structure_constructor (gfc_symbol *sym, gfc_expr **result)
+{
+ match m;
+ gfc_expr *e;
+ gfc_symtree *symtree;
+
+ gfc_get_sym_tree (sym->name, NULL, &symtree, false); /* Can't fail */
+
+ e = gfc_get_expr ();
+ e->symtree = symtree;
+ e->expr_type = EXPR_FUNCTION;
+
+ gcc_assert (sym->attr.flavor == FL_DERIVED
+ && symtree->n.sym->attr.flavor == FL_PROCEDURE);
+ e->value.function.esym = sym;
+ e->symtree->n.sym->attr.generic = 1;
+
+ m = gfc_match_actual_arglist (0, &e->value.function.actual);
+ if (m != MATCH_YES)
+ {
+ gfc_free_expr (e);
+ return m;
+ }
+
+ if (gfc_convert_to_structure_constructor (e, sym, NULL, NULL, false)
+ != SUCCESS)
+ {
+ gfc_free_expr (e);
+ return MATCH_ERROR;
+ }
+
+ *result = e;
+ return MATCH_YES;
}
@@ -2715,7 +2758,7 @@ gfc_match_rvalue (gfc_expr **result)
if (sym == NULL)
m = MATCH_ERROR;
else
- m = gfc_match_structure_constructor (sym, &e, false);
+ goto generic_function;
break;
/* If we're here, then the name is known to be the name of a
@@ -2989,6 +3032,12 @@ gfc_match_rvalue (gfc_expr **result)
e->symtree = symtree;
e->expr_type = EXPR_FUNCTION;
+ if (sym->attr.flavor == FL_DERIVED)
+ {
+ e->value.function.esym = sym;
+ e->symtree->n.sym->attr.generic = 1;
+ }
+
m = gfc_match_actual_arglist (0, &e->value.function.actual);
break;
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index d96b33225ed..6baeff44fa7 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -454,7 +454,8 @@ resolve_formal_arglist (gfc_symbol *proc)
static void
find_arglists (gfc_symbol *sym)
{
- if (sym->attr.if_source == IFSRC_UNKNOWN || sym->ns != gfc_current_ns)
+ if (sym->attr.if_source == IFSRC_UNKNOWN || sym->ns != gfc_current_ns
+ || sym->attr.flavor == FL_DERIVED)
return;
resolve_formal_arglist (sym);
@@ -967,13 +968,6 @@ resolve_structure_cons (gfc_expr *expr, int init)
resolve_fl_derived0 (expr->ts.u.derived);
cons = gfc_constructor_first (expr->value.constructor);
- /* A constructor may have references if it is the result of substituting a
- parameter variable. In this case we just pull out the component we
- want. */
- if (expr->ref)
- comp = expr->ref->u.c.sym->components;
- else
- comp = expr->ts.u.derived->components;
/* See if the user is trying to invoke a structure constructor for one of
the iso_c_binding derived types. */
@@ -992,6 +986,14 @@ resolve_structure_cons (gfc_expr *expr, int init)
&& cons->expr && cons->expr->expr_type == EXPR_NULL)
return SUCCESS;
+ /* A constructor may have references if it is the result of substituting a
+ parameter variable. In this case we just pull out the component we
+ want. */
+ if (expr->ref)
+ comp = expr->ref->u.c.sym->components;
+ else
+ comp = expr->ts.u.derived->components;
+
for (; comp && cons; comp = comp->next, cons = gfc_constructor_next (cons))
{
int rank;
@@ -1401,7 +1403,8 @@ is_illegal_recursion (gfc_symbol* sym, gfc_namespace* context)
gfc_symbol* context_proc;
gfc_namespace* real_context;
- if (sym->attr.flavor == FL_PROGRAM)
+ if (sym->attr.flavor == FL_PROGRAM
+ || sym->attr.flavor == FL_DERIVED)
return false;
gcc_assert (sym->attr.flavor == FL_PROCEDURE);
@@ -2323,6 +2326,7 @@ resolve_generic_f (gfc_expr *expr)
{
gfc_symbol *sym;
match m;
+ gfc_interface *intr = NULL;
sym = expr->symtree->n.sym;
@@ -2335,6 +2339,11 @@ resolve_generic_f (gfc_expr *expr)
return FAILURE;
generic:
+ if (!intr)
+ for (intr = sym->generic; intr; intr = intr->next)
+ if (intr->sym->attr.flavor == FL_DERIVED)
+ break;
+
if (sym->ns->parent == NULL)
break;
gfc_find_symbol (sym->name, sym->ns->parent, 1, &sym);
@@ -2347,16 +2356,25 @@ generic:
/* Last ditch attempt. See if the reference is to an intrinsic
that possesses a matching interface. 14.1.2.4 */
- if (sym && !gfc_is_intrinsic (sym, 0, expr->where))
+ if (sym && !intr && !gfc_is_intrinsic (sym, 0, expr->where))
{
- gfc_error ("There is no specific function for the generic '%s' at %L",
- expr->symtree->n.sym->name, &expr->where);
+ gfc_error ("There is no specific function for the generic '%s' "
+ "at %L", expr->symtree->n.sym->name, &expr->where);
return FAILURE;
}
+ if (intr)
+ {
+ if (gfc_convert_to_structure_constructor (expr, intr->sym, NULL, NULL,
+ false) != SUCCESS)
+ return FAILURE;
+ return resolve_structure_cons (expr, 0);
+ }
+
m = gfc_intrinsic_func_interface (expr, 0);
if (m == MATCH_YES)
return SUCCESS;
+
if (m == MATCH_NO)
gfc_error ("Generic function '%s' at %L is not consistent with a "
"specific intrinsic interface", expr->symtree->n.sym->name,
@@ -3173,10 +3191,10 @@ resolve_function (gfc_expr *expr)
"procedure within a PURE procedure", name, &expr->where);
t = FAILURE;
}
- }
- if (!pure_function (expr, &name) && name && gfc_implicit_pure (NULL))
- gfc_current_ns->proc_name->attr.implicit_pure = 0;
+ if (gfc_implicit_pure (NULL))
+ gfc_current_ns->proc_name->attr.implicit_pure = 0;
+ }
/* Functions without the RECURSIVE attribution are not allowed to
* call themselves. */
@@ -3239,6 +3257,9 @@ pure_subroutine (gfc_code *c, gfc_symbol *sym)
else if (gfc_pure (NULL))
gfc_error ("Subroutine call to '%s' at %L is not PURE", sym->name,
&c->loc);
+
+ if (gfc_implicit_pure (NULL))
+ gfc_current_ns->proc_name->attr.implicit_pure = 0;
}
@@ -5053,6 +5074,9 @@ resolve_variable (gfc_expr *e)
if (sym->assoc && !sym->attr.dimension && e->ref && e->ref->type == REF_ARRAY)
return FAILURE;
+ if (sym->ts.type == BT_DERIVED && sym->ts.u.derived->attr.generic)
+ sym->ts.u.derived = gfc_find_dt_in_generic (sym->ts.u.derived);
+
/* On the other hand, the parser may not have known this is an array;
in this case, we have to add a FULL reference. */
if (sym->assoc && sym->attr.dimension && !e->ref)
@@ -10152,6 +10176,8 @@ resolve_fl_variable_derived (gfc_symbol *sym, int no_init_flag)
{
gfc_symbol *s;
gfc_find_symbol (sym->ts.u.derived->name, sym->ns, 0, &s);
+ if (s && s->attr.generic)
+ s = gfc_find_dt_in_generic (s);
if (s && s->attr.flavor != FL_DERIVED)
{
gfc_error ("The type '%s' cannot be host associated at %L "
@@ -11718,6 +11744,13 @@ resolve_fl_derived0 (gfc_symbol *sym)
}
}
+ if (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.generic)
+ c->ts.u.derived = gfc_find_dt_in_generic (c->ts.u.derived);
+ else if (c->ts.type == BT_CLASS && c->attr.class_ok
+ && CLASS_DATA (c)->ts.u.derived->attr.generic)
+ CLASS_DATA (c)->ts.u.derived
+ = gfc_find_dt_in_generic (CLASS_DATA (c)->ts.u.derived);
+
if (!sym->attr.is_class && c->ts.type == BT_DERIVED && !sym->attr.vtype
&& c->attr.pointer && c->ts.u.derived->components == NULL
&& !c->ts.u.derived->attr.zero_comp)
@@ -11788,6 +11821,23 @@ resolve_fl_derived0 (gfc_symbol *sym)
static gfc_try
resolve_fl_derived (gfc_symbol *sym)
{
+ gfc_symbol *gen_dt = NULL;
+
+ if (!sym->attr.is_class)
+ gfc_find_symbol (sym->name, sym->ns, 0, &gen_dt);
+ if (gen_dt && gen_dt->generic && gen_dt->generic->next
+ && gfc_notify_std (GFC_STD_F2003, "Fortran 2003: Generic name '%s' of "
+ "function '%s' at %L being the same name as derived "
+ "type at %L", sym->name,
+ gen_dt->generic->sym == sym
+ ? gen_dt->generic->next->sym->name
+ : gen_dt->generic->sym->name,
+ gen_dt->generic->sym == sym
+ ? &gen_dt->generic->next->sym->declared_at
+ : &gen_dt->generic->sym->declared_at,
+ &sym->declared_at) == FAILURE)
+ return FAILURE;
+
if (sym->attr.is_class && sym->ts.u.derived == NULL)
{
/* Fix up incomplete CLASS symbols. */
@@ -12191,6 +12241,20 @@ resolve_symbol (gfc_symbol *sym)
}
}
+ if (sym->ts.type == BT_DERIVED && !sym->attr.is_iso_c
+ && sym->ts.u.derived->attr.generic)
+ {
+ sym->ts.u.derived = gfc_find_dt_in_generic (sym->ts.u.derived);
+ if (!sym->ts.u.derived)
+ {
+ gfc_error ("The derived type '%s' at %L is of type '%s', "
+ "which has not been defined", sym->name,
+ &sym->declared_at, sym->ts.u.derived->name);
+ sym->ts.type = BT_UNKNOWN;
+ return;
+ }
+ }
+
/* If the symbol is marked as bind(c), verify it's type and kind. Do not
do this for something that was implicitly typed because that is handled
in gfc_set_default_type. Handle dummy arguments and procedure
@@ -12260,7 +12324,8 @@ resolve_symbol (gfc_symbol *sym)
the type is not declared in the scope of the implicit
statement. Change the type to BT_UNKNOWN, both because it is so
and to prevent an ICE. */
- if (sym->ts.type == BT_DERIVED && sym->ts.u.derived->components == NULL
+ if (sym->ts.type == BT_DERIVED && !sym->attr.is_iso_c
+ && sym->ts.u.derived->components == NULL
&& !sym->ts.u.derived->attr.zero_comp)
{
gfc_error ("The derived type '%s' at %L is of type '%s', "
@@ -12276,22 +12341,9 @@ resolve_symbol (gfc_symbol *sym)
if (sym->ts.type == BT_DERIVED
&& sym->ts.u.derived->attr.use_assoc
&& sym->ns->proc_name
- && sym->ns->proc_name->attr.flavor == FL_MODULE)
- {
- gfc_symbol *ds;
-
- if (resolve_fl_derived (sym->ts.u.derived) == FAILURE)
- return;
-
- gfc_find_symbol (sym->ts.u.derived->name, sym->ns, 1, &ds);
- if (!ds && sym->attr.function && gfc_check_symbol_access (sym))
- {
- symtree = gfc_new_symtree (&sym->ns->sym_root,
- sym->ts.u.derived->name);
- symtree->n.sym = sym->ts.u.derived;
- sym->ts.u.derived->refs++;
- }
- }
+ && sym->ns->proc_name->attr.flavor == FL_MODULE
+ && resolve_fl_derived (sym->ts.u.derived) == FAILURE)
+ return;
/* Unless the derived-type declaration is use associated, Fortran 95
does not allow public entries of private derived types.
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
index 33ec706f40a..de42297981e 100644
--- a/gcc/fortran/symbol.c
+++ b/gcc/fortran/symbol.c
@@ -742,9 +742,10 @@ check_conflict (symbol_attribute *attr, const char *name, locus *where)
conf2 (asynchronous);
conf2 (threadprivate);
conf2 (value);
- conf2 (is_bind_c);
conf2 (codimension);
conf2 (result);
+ if (!attr->is_iso_c)
+ conf2 (is_bind_c);
break;
default:
@@ -1949,6 +1950,9 @@ gfc_use_derived (gfc_symbol *sym)
if (!sym)
return NULL;
+ if (sym->attr.generic)
+ sym = gfc_find_dt_in_generic (sym);
+
if (sym->components != NULL || sym->attr.zero_comp)
return sym; /* Already defined. */
@@ -2880,7 +2884,15 @@ gfc_undo_symbols (void)
}
}
- gfc_delete_symtree (&p->ns->sym_root, p->name);
+ /* The derived type is saved in the symtree with the first
+ letter capitalized; the all lower-case version to the
+ derived type contains its associated generic function. */
+ if (p->attr.flavor == FL_DERIVED)
+ gfc_delete_symtree (&p->ns->sym_root, gfc_get_string ("%c%s",
+ (char) TOUPPER ((unsigned char) p->name[0]),
+ &p->name[1]));
+ else
+ gfc_delete_symtree (&p->ns->sym_root, p->name);
gfc_release_symbol (p);
continue;
@@ -3752,13 +3764,11 @@ gen_special_c_interop_ptr (int ptr_id, const char *ptr_name,
"create symbol for %s", ptr_name);
}
- /* Set up the symbol's important fields. Save attr required so we can
- initialize the ptr to NULL. */
- tmp_sym->attr.save = SAVE_EXPLICIT;
tmp_sym->ts.is_c_interop = 1;
tmp_sym->attr.is_c_interop = 1;
tmp_sym->ts.is_iso_c = 1;
tmp_sym->ts.type = BT_DERIVED;
+ tmp_sym->attr.flavor = FL_PARAMETER;
/* The c_ptr and c_funptr derived types will provide the
definition for c_null_ptr and c_null_funptr, respectively. */
@@ -3773,15 +3783,15 @@ gen_special_c_interop_ptr (int ptr_id, const char *ptr_name,
that has arg(s) of the missing type. In this case, a
regular version of the thing should have been put in the
current ns. */
+
generate_isocbinding_symbol (module_name, ptr_id == ISOCBINDING_NULL_PTR
? ISOCBINDING_PTR : ISOCBINDING_FUNPTR,
(const char *) (ptr_id == ISOCBINDING_NULL_PTR
- ? "_gfortran_iso_c_binding_c_ptr"
- : "_gfortran_iso_c_binding_c_funptr"));
-
+ ? "c_ptr"
+ : "c_funptr"));
tmp_sym->ts.u.derived =
- get_iso_c_binding_dt (ptr_id == ISOCBINDING_NULL_PTR
- ? ISOCBINDING_PTR : ISOCBINDING_FUNPTR);
+ get_iso_c_binding_dt (ptr_id == ISOCBINDING_NULL_PTR
+ ? ISOCBINDING_PTR : ISOCBINDING_FUNPTR);
}
/* Module name is some mangled version of iso_c_binding. */
@@ -3806,9 +3816,6 @@ gen_special_c_interop_ptr (int ptr_id, const char *ptr_name,
c->expr = gfc_get_expr ();
c->expr->expr_type = EXPR_NULL;
c->expr->ts.is_iso_c = 1;
- /* Must declare c_null_ptr and c_null_funptr as having the
- PARAMETER attribute so they can be used in init expressions. */
- tmp_sym->attr.flavor = FL_PARAMETER;
return SUCCESS;
}
@@ -3859,9 +3866,9 @@ gen_cptr_param (gfc_formal_arglist **head,
const char *c_ptr_type = NULL;
if (iso_c_sym_id == ISOCBINDING_F_PROCPOINTER)
- c_ptr_type = "_gfortran_iso_c_binding_c_funptr";
+ c_ptr_type = "c_funptr";
else
- c_ptr_type = "_gfortran_iso_c_binding_c_ptr";
+ c_ptr_type = "c_ptr";
if(c_ptr_name == NULL)
c_ptr_in = "gfc_cptr__";
@@ -4338,19 +4345,31 @@ generate_isocbinding_symbol (const char *mod_name, iso_c_binding_symbol s,
: c_interop_kinds_table[s].name;
gfc_symtree *tmp_symtree = NULL;
gfc_symbol *tmp_sym = NULL;
- gfc_dt_list **dt_list_ptr = NULL;
- gfc_component *tmp_comp = NULL;
- char comp_name[(GFC_MAX_SYMBOL_LEN * 2) + 1];
int index;
if (gfc_notification_std (std_for_isocbinding_symbol (s)) == ERROR)
return;
+
tmp_symtree = gfc_find_symtree (gfc_current_ns->sym_root, name);
- /* Already exists in this scope so don't re-add it.
- TODO: we should probably check that it's really the same symbol. */
- if (tmp_symtree != NULL)
- return;
+ /* Already exists in this scope so don't re-add it. */
+ if (tmp_symtree != NULL && (tmp_sym = tmp_symtree->n.sym) != NULL
+ && (!tmp_sym->attr.generic
+ || (tmp_sym = gfc_find_dt_in_generic (tmp_sym)) != NULL)
+ && tmp_sym->from_intmod == INTMOD_ISO_C_BINDING)
+ {
+ if (tmp_sym->attr.flavor == FL_DERIVED
+ && !get_iso_c_binding_dt (tmp_sym->intmod_sym_id))
+ {
+ gfc_dt_list *dt_list;
+ dt_list = gfc_get_dt_list ();
+ dt_list->derived = tmp_sym;
+ dt_list->next = gfc_derived_types;
+ gfc_derived_types = dt_list;
+ }
+
+ return;
+ }
/* Create the sym tree in the current ns. */
gfc_get_sym_tree (name, gfc_current_ns, &tmp_symtree, false);
@@ -4443,64 +4462,112 @@ generate_isocbinding_symbol (const char *mod_name, iso_c_binding_symbol s,
case ISOCBINDING_PTR:
case ISOCBINDING_FUNPTR:
-
- /* Initialize an integer constant expression node. */
- tmp_sym->attr.flavor = FL_DERIVED;
- tmp_sym->ts.is_c_interop = 1;
- tmp_sym->attr.is_c_interop = 1;
- tmp_sym->attr.is_iso_c = 1;
- tmp_sym->ts.is_iso_c = 1;
- tmp_sym->ts.type = BT_DERIVED;
-
- /* A derived type must have the bind attribute to be
- interoperable (J3/04-007, Section 15.2.3), even though
- the binding label is not used. */
- tmp_sym->attr.is_bind_c = 1;
-
- tmp_sym->attr.referenced = 1;
-
- tmp_sym->ts.u.derived = tmp_sym;
-
- /* Add the symbol created for the derived type to the current ns. */
- dt_list_ptr = &(gfc_derived_types);
- while (*dt_list_ptr != NULL && (*dt_list_ptr)->next != NULL)
- dt_list_ptr = &((*dt_list_ptr)->next);
-
- /* There is already at least one derived type in the list, so append
- the one we're currently building for c_ptr or c_funptr. */
- if (*dt_list_ptr != NULL)
- dt_list_ptr = &((*dt_list_ptr)->next);
- (*dt_list_ptr) = gfc_get_dt_list ();
- (*dt_list_ptr)->derived = tmp_sym;
- (*dt_list_ptr)->next = NULL;
-
- /* Set up the component of the derived type, which will be
- an integer with kind equal to c_ptr_size. Mangle the name of
- the field for the c_address to prevent the curious user from
- trying to access it from Fortran. */
- sprintf (comp_name, "__%s_%s", tmp_sym->name, "c_address");
- gfc_add_component (tmp_sym, comp_name, &tmp_comp);
- if (tmp_comp == NULL)
+ {
+ gfc_interface *intr, *head;
+ gfc_symbol *dt_sym;
+ const char *hidden_name;
+ gfc_dt_list **dt_list_ptr = NULL;
+ gfc_component *tmp_comp = NULL;
+ char comp_name[(GFC_MAX_SYMBOL_LEN * 2) + 1];
+
+ hidden_name = gfc_get_string ("%c%s",
+ (char) TOUPPER ((unsigned char) tmp_sym->name[0]),
+ &tmp_sym->name[1]);
+
+ /* Generate real derived type. */
+ tmp_symtree = gfc_find_symtree (gfc_current_ns->sym_root,
+ hidden_name);
+
+ if (tmp_symtree != NULL)
+ gcc_unreachable ();
+ gfc_get_sym_tree (hidden_name, gfc_current_ns, &tmp_symtree, false);
+ if (tmp_symtree)
+ dt_sym = tmp_symtree->n.sym;
+ else
+ gcc_unreachable ();
+
+ /* Generate an artificial generic function. */
+ dt_sym->name = gfc_get_string (tmp_sym->name);
+ head = tmp_sym->generic;
+ intr = gfc_get_interface ();
+ intr->sym = dt_sym;
+ intr->where = gfc_current_locus;
+ intr->next = head;
+ tmp_sym->generic = intr;
+
+ if (!tmp_sym->attr.generic
+ && gfc_add_generic (&tmp_sym->attr, tmp_sym->name, NULL)
+ == FAILURE)
+ return;
+
+ if (!tmp_sym->attr.function
+ && gfc_add_function (&tmp_sym->attr, tmp_sym->name, NULL)
+ == FAILURE)
+ return;
+
+ /* Say what module this symbol belongs to. */
+ dt_sym->module = gfc_get_string (mod_name);
+ dt_sym->from_intmod = INTMOD_ISO_C_BINDING;
+ dt_sym->intmod_sym_id = s;
+
+ /* Initialize an integer constant expression node. */
+ dt_sym->attr.flavor = FL_DERIVED;
+ dt_sym->ts.is_c_interop = 1;
+ dt_sym->attr.is_c_interop = 1;
+ dt_sym->attr.is_iso_c = 1;
+ dt_sym->ts.is_iso_c = 1;
+ dt_sym->ts.type = BT_DERIVED;
+
+ /* A derived type must have the bind attribute to be
+ interoperable (J3/04-007, Section 15.2.3), even though
+ the binding label is not used. */
+ dt_sym->attr.is_bind_c = 1;
+
+ dt_sym->attr.referenced = 1;
+ dt_sym->ts.u.derived = dt_sym;
+
+ /* Add the symbol created for the derived type to the current ns. */
+ dt_list_ptr = &(gfc_derived_types);
+ while (*dt_list_ptr != NULL && (*dt_list_ptr)->next != NULL)
+ dt_list_ptr = &((*dt_list_ptr)->next);
+
+ /* There is already at least one derived type in the list, so append
+ the one we're currently building for c_ptr or c_funptr. */
+ if (*dt_list_ptr != NULL)
+ dt_list_ptr = &((*dt_list_ptr)->next);
+ (*dt_list_ptr) = gfc_get_dt_list ();
+ (*dt_list_ptr)->derived = dt_sym;
+ (*dt_list_ptr)->next = NULL;
+
+ /* Set up the component of the derived type, which will be
+ an integer with kind equal to c_ptr_size. Mangle the name of
+ the field for the c_address to prevent the curious user from
+ trying to access it from Fortran. */
+ sprintf (comp_name, "__%s_%s", dt_sym->name, "c_address");
+ gfc_add_component (dt_sym, comp_name, &tmp_comp);
+ if (tmp_comp == NULL)
gfc_internal_error ("generate_isocbinding_symbol(): Unable to "
"create component for c_address");
- tmp_comp->ts.type = BT_INTEGER;
+ tmp_comp->ts.type = BT_INTEGER;
- /* Set this because the module will need to read/write this field. */
- tmp_comp->ts.f90_type = BT_INTEGER;
+ /* Set this because the module will need to read/write this field. */
+ tmp_comp->ts.f90_type = BT_INTEGER;
- /* The kinds for c_ptr and c_funptr are the same. */
- index = get_c_kind ("c_ptr", c_interop_kinds_table);
- tmp_comp->ts.kind = c_interop_kinds_table[index].value;
+ /* The kinds for c_ptr and c_funptr are the same. */
+ index = get_c_kind ("c_ptr", c_interop_kinds_table);
+ tmp_comp->ts.kind = c_interop_kinds_table[index].value;
- tmp_comp->attr.pointer = 0;
- tmp_comp->attr.dimension = 0;
+ tmp_comp->attr.pointer = 0;
+ tmp_comp->attr.dimension = 0;
- /* Mark the component as C interoperable. */
- tmp_comp->ts.is_c_interop = 1;
+ /* Mark the component as C interoperable. */
+ tmp_comp->ts.is_c_interop = 1;
+
+ /* Make it use associated (iso_c_binding module). */
+ dt_sym->attr.use_assoc = 1;
+ }
- /* Make it use associated (iso_c_binding module). */
- tmp_sym->attr.use_assoc = 1;
break;
case ISOCBINDING_NULL_PTR:
@@ -4550,21 +4617,20 @@ generate_isocbinding_symbol (const char *mod_name, iso_c_binding_symbol s,
tmp_sym->ts.u.derived =
get_iso_c_binding_dt (ISOCBINDING_FUNPTR);
- if (tmp_sym->ts.u.derived == NULL)
- {
+ if (tmp_sym->ts.u.derived == NULL)
+ {
/* Create the necessary derived type so we can continue
processing the file. */
- generate_isocbinding_symbol
+ generate_isocbinding_symbol
(mod_name, s == ISOCBINDING_FUNLOC
- ? ISOCBINDING_FUNPTR : ISOCBINDING_PTR,
- (const char *)(s == ISOCBINDING_FUNLOC
- ? "_gfortran_iso_c_binding_c_funptr"
- : "_gfortran_iso_c_binding_c_ptr"));
+ ? ISOCBINDING_FUNPTR : ISOCBINDING_PTR,
+ (const char *)(s == ISOCBINDING_FUNLOC
+ ? "c_funptr" : "c_ptr"));
tmp_sym->ts.u.derived =
- get_iso_c_binding_dt (s == ISOCBINDING_FUNLOC
- ? ISOCBINDING_FUNPTR
- : ISOCBINDING_PTR);
- }
+ get_iso_c_binding_dt (s == ISOCBINDING_FUNLOC
+ ? ISOCBINDING_FUNPTR
+ : ISOCBINDING_PTR);
+ }
/* The function result is itself (no result clause). */
tmp_sym->result = tmp_sym;
@@ -4712,6 +4778,9 @@ gfc_get_typebound_proc (gfc_typebound_proc *tb0)
gfc_symbol*
gfc_get_derived_super_type (gfc_symbol* derived)
{
+ if (derived && derived->attr.generic)
+ derived = gfc_find_dt_in_generic (derived);
+
if (!derived->attr.extension)
return NULL;
@@ -4719,6 +4788,9 @@ gfc_get_derived_super_type (gfc_symbol* derived)
gcc_assert (derived->components->ts.type == BT_DERIVED);
gcc_assert (derived->components->ts.u.derived);
+ if (derived->components->ts.u.derived->attr.generic)
+ return gfc_find_dt_in_generic (derived->components->ts.u.derived);
+
return derived->components->ts.u.derived;
}
@@ -4814,3 +4886,19 @@ gfc_is_associate_pointer (gfc_symbol* sym)
return true;
}
+
+
+gfc_symbol *
+gfc_find_dt_in_generic (gfc_symbol *sym)
+{
+ gfc_interface *intr = NULL;
+
+ if (!sym || sym->attr.flavor == FL_DERIVED)
+ return sym;
+
+ if (sym->attr.generic)
+ for (intr = (sym ? sym->generic : NULL); intr; intr = intr->next)
+ if (intr->sym->attr.flavor == FL_DERIVED)
+ break;
+ return intr ? intr->sym : NULL;
+}
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 262743d0d37..ee8f89693b4 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -1087,7 +1087,7 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss,
for (s = ss; s; s = s->parent)
for (n = 0; n < s->loop->dimen; n++)
{
- dim = get_scalarizer_dim_for_array_dim (ss, ss->dim[n]);
+ dim = get_scalarizer_dim_for_array_dim (ss, s->dim[n]);
/* For a callee allocated array express the loop bounds in terms
of the descriptor fields. */
@@ -4341,9 +4341,9 @@ set_loop_bounds (gfc_loopinfo *loop)
}
/* Transform everything so we have a simple incrementing variable. */
- if (n < loop->dimen && integer_onep (info->stride[dim]))
+ if (integer_onep (info->stride[dim]))
info->delta[dim] = gfc_index_zero_node;
- else if (n < loop->dimen)
+ else
{
/* Set the delta for this section. */
info->delta[dim] = gfc_evaluate_now (loop->from[n], &loop->pre);
@@ -5027,6 +5027,11 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr)
tree index, range;
VEC(constructor_elt,gc) *v = NULL;
+ if (expr->expr_type == EXPR_VARIABLE
+ && expr->symtree->n.sym->attr.flavor == FL_PARAMETER
+ && expr->symtree->n.sym->value)
+ expr = expr->symtree->n.sym->value;
+
switch (expr->expr_type)
{
case EXPR_CONSTANT:
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 80e4f555d1c..67bd3e233f0 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -699,6 +699,18 @@ gfc_get_module_backend_decl (gfc_symbol *sym)
}
else if (sym->attr.flavor == FL_DERIVED)
{
+ if (s && s->attr.flavor == FL_PROCEDURE)
+ {
+ gfc_interface *intr;
+ gcc_assert (s->attr.generic);
+ for (intr = s->generic; intr; intr = intr->next)
+ if (intr->sym->attr.flavor == FL_DERIVED)
+ {
+ s = intr->sym;
+ break;
+ }
+ }
+
if (!s->backend_decl)
s->backend_decl = gfc_get_derived_type (s);
gfc_copy_dt_decls_ifequal (s, sym, true);
@@ -706,7 +718,7 @@ gfc_get_module_backend_decl (gfc_symbol *sym)
}
else if (s->backend_decl)
{
- if (sym->ts.type == BT_DERIVED)
+ if (sym->ts.type == BT_DERIVED || sym->ts.type == BT_CLASS)
gfc_copy_dt_decls_ifequal (s->ts.u.derived, sym->ts.u.derived,
true);
else if (sym->ts.type == BT_CHARACTER)
@@ -1459,6 +1471,10 @@ gfc_get_symbol_decl (gfc_symbol * sym)
&& !sym->attr.proc_pointer)
DECL_BY_REFERENCE (decl) = 1;
+ if (sym->attr.vtab
+ || (sym->name[0] == '_' && strncmp ("__def_init", sym->name, 10) == 0))
+ GFC_DECL_PUSH_TOPLEVEL (decl) = 1;
+
return decl;
}
@@ -1654,6 +1670,11 @@ gfc_get_extern_function_decl (gfc_symbol * sym)
gfc_find_symbol (sym->name, gsym->ns, 0, &s);
if (s && s->backend_decl)
{
+ if (sym->ts.type == BT_DERIVED || sym->ts.type == BT_CLASS)
+ gfc_copy_dt_decls_ifequal (s->ts.u.derived, sym->ts.u.derived,
+ true);
+ else if (sym->ts.type == BT_CHARACTER)
+ sym->ts.u.cl->backend_decl = s->ts.u.cl->backend_decl;
sym->backend_decl = s->backend_decl;
return sym->backend_decl;
}
@@ -1879,7 +1900,8 @@ build_function_decl (gfc_symbol * sym, bool global)
/* Layout the function declaration and put it in the binding level
of the current function. */
- if (global)
+ if (global
+ || (sym->name[0] == '_' && strncmp ("__copy", sym->name, 6) == 0))
pushdecl_top_level (fndecl);
else
pushdecl (fndecl);
@@ -4035,7 +4057,18 @@ gfc_trans_use_stmts (gfc_namespace * ns)
st = gfc_find_symtree (ns->sym_root,
rent->local_name[0]
? rent->local_name : rent->use_name);
- gcc_assert (st);
+
+ /* The following can happen if a derived type is renamed. */
+ if (!st)
+ {
+ char *name;
+ name = xstrdup (rent->local_name[0]
+ ? rent->local_name : rent->use_name);
+ name[0] = (char) TOUPPER ((unsigned char) name[0]);
+ st = gfc_find_symtree (ns->sym_root, name);
+ free (name);
+ gcc_assert (st);
+ }
/* Sometimes, generic interfaces wind up being over-ruled by a
local symbol (see PR41062). */
@@ -5293,7 +5326,10 @@ gfc_generate_function_code (gfc_namespace * ns)
next = DECL_CHAIN (decl);
DECL_CHAIN (decl) = NULL_TREE;
- pushdecl (decl);
+ if (GFC_DECL_PUSH_TOPLEVEL (decl))
+ pushdecl_top_level (decl);
+ else
+ pushdecl (decl);
decl = next;
}
saved_function_decls = NULL_TREE;
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index 0d793f96858..b21be45a96d 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -1259,7 +1259,8 @@ gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
loc = code->ext.iterator->start->where.lb->location;
/* Initialize the DO variable: dovar = from. */
- gfc_add_modify_loc (loc, pblock, dovar, from);
+ gfc_add_modify_loc (loc, pblock, dovar,
+ fold_convert (TREE_TYPE(dovar), from));
/* Save value for do-tinkering checking. */
if (gfc_option.rtcheck & GFC_RTCHECK_DO)
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index ce607d8dbfd..d643c2e45b8 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -2188,6 +2188,9 @@ gfc_copy_dt_decls_ifequal (gfc_symbol *from, gfc_symbol *to,
gfc_component *to_cm;
gfc_component *from_cm;
+ if (from == to)
+ return 1;
+
if (from->backend_decl == NULL
|| !gfc_compare_derived_types (from, to))
return 0;
@@ -2257,6 +2260,10 @@ gfc_get_derived_type (gfc_symbol * derived)
gfc_dt_list *dt;
gfc_namespace *ns;
+ if (derived && derived->attr.flavor == FL_PROCEDURE
+ && derived->attr.generic)
+ derived = gfc_find_dt_in_generic (derived);
+
gcc_assert (derived && derived->attr.flavor == FL_DERIVED);
/* See if it's one of the iso_c_binding derived types. */
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 22033d38d15..8fc7599473d 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -802,6 +802,7 @@ struct GTY((variable_size)) lang_decl {
#define GFC_DECL_CRAY_POINTEE(node) DECL_LANG_FLAG_4(node)
#define GFC_DECL_RESULT(node) DECL_LANG_FLAG_5(node)
#define GFC_DECL_SUBREF_ARRAY_P(node) DECL_LANG_FLAG_6(node)
+#define GFC_DECL_PUSH_TOPLEVEL(node) DECL_LANG_FLAG_7(node)
/* An array descriptor. */
#define GFC_DESCRIPTOR_TYPE_P(node) TYPE_LANG_FLAG_1(node)
diff --git a/gcc/function.c b/gcc/function.c
index 0ee69ef22b6..664858a29e3 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -6230,7 +6230,8 @@ thread_prologue_and_epilogue_insns (void)
&& !active_insn_between (BB_HEAD (last_bb), BB_END (last_bb)))
convert_jumps_to_returns (last_bb, false, NULL);
- if (EDGE_COUNT (exit_fallthru_edge->src->preds) != 0)
+ if (EDGE_COUNT (last_bb->preds) != 0
+ && single_succ_p (last_bb))
{
last_bb = emit_return_for_exit (exit_fallthru_edge, false);
epilogue_end = returnjump = BB_END (last_bb);
diff --git a/gcc/gcov.c b/gcc/gcov.c
index dffb827bdf7..29907a311e3 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -406,6 +406,11 @@ main (int argc, char **argv)
/* Handle response files. */
expandargv (&argc, &argv);
+ a_names = 10;
+ names = XNEWVEC (name_map_t, a_names);
+ a_sources = 10;
+ sources = XNEWVEC (source_t, a_sources);
+
argno = process_args (argc, argv);
if (optind == argc)
print_usage (true);
@@ -874,8 +879,6 @@ find_source (const char *file_name)
{
/* Extend the name map array -- we'll be inserting one or two
entries. */
- if (!a_names)
- a_names = 10;
a_names *= 2;
name_map = XNEWVEC (name_map_t, a_names);
memcpy (name_map, names, n_names * sizeof (*names));
@@ -894,8 +897,6 @@ find_source (const char *file_name)
if (n_sources == a_sources)
{
- if (!a_sources)
- a_sources = 10;
a_sources *= 2;
src = XNEWVEC (source_t, a_sources);
memcpy (src, sources, n_sources * sizeof (*sources));
@@ -1688,10 +1689,15 @@ canonicalize_name (const char *name)
{
/* '..', we can only elide it and the previous directory, if
we're not a symlink. */
- struct stat buf;
-
+ struct stat ATTRIBUTE_UNUSED buf;
+
*ptr = 0;
- if (dd_base == ptr || stat (result, &buf) || S_ISLNK (buf.st_mode))
+ if (dd_base == ptr
+#if defined (S_ISLNK)
+ /* S_ISLNK is not POSIX.1-1996. */
+ || stat (result, &buf) || S_ISLNK (buf.st_mode)
+#endif
+ )
{
/* Cannot elide, or unreadable or a symlink. */
dd_base = ptr + 2 + slash;
diff --git a/gcc/gimple-streamer-in.c b/gcc/gimple-streamer-in.c
index 862c5b08e3a..1facb3296f6 100644
--- a/gcc/gimple-streamer-in.c
+++ b/gcc/gimple-streamer-in.c
@@ -238,6 +238,10 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
case GIMPLE_PREDICT:
break;
+ case GIMPLE_TRANSACTION:
+ gimple_transaction_set_label (stmt, stream_read_tree (ib, data_in));
+ break;
+
default:
internal_error ("bytecode stream: unknown GIMPLE statement tag %s",
lto_tag_name (tag));
diff --git a/gcc/gimple-streamer-out.c b/gcc/gimple-streamer-out.c
index 78ed2815dde..a7e73fa8db2 100644
--- a/gcc/gimple-streamer-out.c
+++ b/gcc/gimple-streamer-out.c
@@ -151,6 +151,11 @@ output_gimple_stmt (struct output_block *ob, gimple stmt)
case GIMPLE_PREDICT:
break;
+ case GIMPLE_TRANSACTION:
+ gcc_assert (gimple_transaction_body (stmt) == NULL);
+ stream_write_tree (ob, gimple_transaction_label (stmt), true);
+ break;
+
default:
gcc_unreachable ();
}
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 6168d33ac05..071c6515b4c 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -2858,8 +2858,18 @@ is_gimple_ip_invariant_address (const_tree t)
return false;
op = strip_invariant_refs (TREE_OPERAND (t, 0));
+ if (!op)
+ return false;
+
+ if (TREE_CODE (op) == MEM_REF)
+ {
+ const_tree op0 = TREE_OPERAND (op, 0);
+ return (TREE_CODE (op0) == ADDR_EXPR
+ && (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))
+ || decl_address_ip_invariant_p (TREE_OPERAND (op0, 0))));
+ }
- return op && (CONSTANT_CLASS_P (op) || decl_address_ip_invariant_p (op));
+ return CONSTANT_CLASS_P (op) || decl_address_ip_invariant_p (op);
}
/* Return true if T is a GIMPLE minimal invariant. It's a restricted
diff --git a/gcc/hard-reg-set.h b/gcc/hard-reg-set.h
index 9cd7c8bb962..9823a5b3441 100644
--- a/gcc/hard-reg-set.h
+++ b/gcc/hard-reg-set.h
@@ -583,6 +583,13 @@ hard_reg_set_iter_next (hard_reg_set_iterator *iter, unsigned *regno)
extern char global_regs[FIRST_PSEUDO_REGISTER];
struct target_hard_regs {
+ /* The set of registers that actually exist on the current target. */
+ HARD_REG_SET x_accessible_reg_set;
+
+ /* The set of registers that should be considered to be register
+ operands. It is a subset of x_accessible_reg_set. */
+ HARD_REG_SET x_operand_reg_set;
+
/* Indexed by hard register number, contains 1 for registers
that are fixed use (stack pointer, pc, frame pointer, etc.;.
These are the registers that cannot be used to allocate
@@ -659,6 +666,10 @@ extern struct target_hard_regs *this_target_hard_regs;
#define this_target_hard_regs (&default_target_hard_regs)
#endif
+#define accessible_reg_set \
+ (this_target_hard_regs->x_accessible_reg_set)
+#define operand_reg_set \
+ (this_target_hard_regs->x_operand_reg_set)
#define fixed_regs \
(this_target_hard_regs->x_fixed_regs)
#define fixed_reg_set \
diff --git a/gcc/incpath.c b/gcc/incpath.c
index 07a765f3fc0..6b683a053dc 100644
--- a/gcc/incpath.c
+++ b/gcc/incpath.c
@@ -460,6 +460,15 @@ register_include_chains (cpp_reader *pfile, const char *sysroot,
cpp_set_include_chains (pfile, heads[QUOTE], heads[BRACKET],
quote_ignores_source_dir);
}
+
+/* Return the current chain of cpp dirs. */
+
+struct cpp_dir *
+get_added_cpp_dirs (int chain)
+{
+ return heads[chain];
+}
+
#if !(defined TARGET_EXTRA_INCLUDES) || !(defined TARGET_EXTRA_PRE_INCLUDES)
static void hook_void_charptr_charptr_int (const char *sysroot ATTRIBUTE_UNUSED,
const char *iprefix ATTRIBUTE_UNUSED,
diff --git a/gcc/incpath.h b/gcc/incpath.h
index df5b6b18129..4c647a39fe7 100644
--- a/gcc/incpath.h
+++ b/gcc/incpath.h
@@ -22,6 +22,7 @@ extern void register_include_chains (cpp_reader *, const char *,
const char *, const char *,
int, int, int);
extern void add_cpp_dir_path (struct cpp_dir *, int);
+extern struct cpp_dir *get_added_cpp_dirs (int);
struct target_c_incpath_s {
/* Do extra includes processing. STDINC is false iff -nostdinc was given. */
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 45cb00b2169..10e1834ce7b 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -693,7 +693,7 @@ ipa_value_from_known_type_jfunc (struct ipa_jump_func *jfunc)
describes the caller node so that pass-through jump functions can be
evaluated. */
-static tree
+tree
ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
{
if (jfunc->type == IPA_JF_CONST)
@@ -753,21 +753,6 @@ ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
return NULL_TREE;
}
-/* Determine whether JFUNC evaluates to a constant and if so, return it.
- Otherwise return NULL. INFO describes the caller node so that pass-through
- jump functions can be evaluated. */
-
-tree
-ipa_cst_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
-{
- tree res = ipa_value_from_jfunc (info, jfunc);
-
- if (res && TREE_CODE (res) == TREE_BINFO)
- return NULL_TREE;
- else
- return res;
-}
-
/* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
bottom, not containing a variable component and without any known value at
@@ -1112,10 +1097,10 @@ propagate_constants_accross_call (struct cgraph_edge *cs)
(which can contain both constants and binfos) or KNOWN_BINFOS (which can be
NULL) return the destination. */
-static tree
-get_indirect_edge_target (struct cgraph_edge *ie,
- VEC (tree, heap) *known_vals,
- VEC (tree, heap) *known_binfos)
+tree
+ipa_get_indirect_edge_target (struct cgraph_edge *ie,
+ VEC (tree, heap) *known_vals,
+ VEC (tree, heap) *known_binfos)
{
int param_index = ie->indirect_info->param_index;
HOST_WIDE_INT token, anc_offset;
@@ -1185,7 +1170,7 @@ devirtualization_time_bonus (struct cgraph_node *node,
struct inline_summary *isummary;
tree target;
- target = get_indirect_edge_target (ie, known_csts, known_binfos);
+ target = ipa_get_indirect_edge_target (ie, known_csts, known_binfos);
if (!target)
continue;
@@ -1344,7 +1329,8 @@ estimate_local_effects (struct cgraph_node *node)
init_caller_stats (&stats);
cgraph_for_node_and_aliases (node, gather_caller_stats, &stats, false);
- estimate_ipcp_clone_size_and_time (node, known_csts, &size, &time);
+ estimate_ipcp_clone_size_and_time (node, known_csts, known_binfos,
+ &size, &time);
time -= devirtualization_time_bonus (node, known_csts, known_binfos);
time -= removable_params_cost;
size -= stats.n_calls * removable_params_cost;
@@ -1415,7 +1401,8 @@ estimate_local_effects (struct cgraph_node *node)
else
continue;
- estimate_ipcp_clone_size_and_time (node, known_csts, &size, &time);
+ estimate_ipcp_clone_size_and_time (node, known_csts, known_binfos,
+ &size, &time);
time_benefit = base_time - time
+ devirtualization_time_bonus (node, known_csts, known_binfos)
+ removable_params_cost + emc;
@@ -1673,7 +1660,7 @@ ipcp_discover_new_direct_edges (struct cgraph_node *node,
tree target;
next_ie = ie->next_callee;
- target = get_indirect_edge_target (ie, known_vals, NULL);
+ target = ipa_get_indirect_edge_target (ie, known_vals, NULL);
if (target)
ipa_make_edge_direct_to_target (ie, target);
}
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index 91aa6123d91..9ff247b103a 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -710,15 +710,25 @@ evaluate_conditions_for_known_args (struct cgraph_node *node,
/* Work out what conditions might be true at invocation of E. */
-static clause_t
-evaluate_conditions_for_edge (struct cgraph_edge *e, bool inline_p)
+static void
+evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p,
+ clause_t *clause_ptr,
+ VEC (tree, heap) **known_vals_ptr,
+ VEC (tree, heap) **known_binfos_ptr)
{
- clause_t clause = inline_p ? 0 : 1 << predicate_not_inlined_condition;
struct cgraph_node *callee = cgraph_function_or_thunk_node (e->callee, NULL);
struct inline_summary *info = inline_summary (callee);
int i;
- if (ipa_node_params_vector && info->conds)
+ if (clause_ptr)
+ *clause_ptr = inline_p ? 0 : 1 << predicate_not_inlined_condition;
+ if (known_vals_ptr)
+ *known_vals_ptr = NULL;
+ if (known_binfos_ptr)
+ *known_binfos_ptr = NULL;
+
+ if (ipa_node_params_vector
+ && ((clause_ptr && info->conds) || known_vals_ptr || known_binfos_ptr))
{
struct ipa_node_params *parms_info;
struct ipa_edge_args *args = IPA_EDGE_REF (e);
@@ -731,29 +741,42 @@ evaluate_conditions_for_edge (struct cgraph_edge *e, bool inline_p)
else
parms_info = IPA_NODE_REF (e->caller);
- if (count)
- VEC_safe_grow_cleared (tree, heap, known_vals, count);
+ if (count && (info->conds || known_vals_ptr))
+ VEC_safe_grow_cleared (tree, heap, known_vals, count);
+ if (count && known_binfos_ptr)
+ VEC_safe_grow_cleared (tree, heap, *known_binfos_ptr, count);
+
for (i = 0; i < count; i++)
{
- tree cst = ipa_cst_from_jfunc (parms_info,
- ipa_get_ith_jump_func (args, i));
+ tree cst = ipa_value_from_jfunc (parms_info,
+ ipa_get_ith_jump_func (args, i));
if (cst)
- VEC_replace (tree, known_vals, i, cst);
+ {
+ if (info->conds && TREE_CODE (cst) != TREE_BINFO)
+ VEC_replace (tree, known_vals, i, cst);
+ else if (known_binfos_ptr != NULL)
+ VEC_replace (tree, *known_binfos_ptr, i, cst);
+ }
else if (inline_p
&& !VEC_index (inline_param_summary_t,
es->param,
i)->change_prob)
VEC_replace (tree, known_vals, i, error_mark_node);
}
- clause = evaluate_conditions_for_known_args (callee,
- inline_p, known_vals);
- VEC_free (tree, heap, known_vals);
+
+ if (clause_ptr && info->conds)
+ *clause_ptr = evaluate_conditions_for_known_args (callee, inline_p,
+ known_vals);
+
+ if (known_vals_ptr)
+ *known_vals_ptr = known_vals;
+ else
+ VEC_free (tree, heap, known_vals);
}
- else
- for (i = 0; i < (int)VEC_length (condition, info->conds); i++)
- clause |= 1 << (i + predicate_first_dynamic_condition);
- return clause;
+ if (clause_ptr && !info->conds)
+ for (i = 0; i < (int)VEC_length (condition, info->conds); i++)
+ *clause_ptr |= 1 << (i + predicate_first_dynamic_condition);
}
@@ -2169,11 +2192,71 @@ estimate_edge_size_and_time (struct cgraph_edge *e, int *size, int *time,
}
-/* Increase SIZE and TIME for size and time needed to handle all calls in NODE. */
+/* Estimate benefit devirtualizing indirect edge IE, provided KNOWN_VALS and
+ KNOWN_BINFOS. */
+
+static void
+estimate_edge_devirt_benefit (struct cgraph_edge *ie,
+ int *size, int *time, int prob,
+ VEC (tree, heap) *known_vals,
+ VEC (tree, heap) *known_binfos)
+{
+ tree target;
+ struct cgraph_node *callee;
+ struct inline_summary *isummary;
+ int edge_size = 0, edge_time = 0;
+
+ if (!known_vals || !known_binfos)
+ return;
+
+ target = ipa_get_indirect_edge_target (ie, known_vals, known_binfos);
+ if (!target)
+ return;
+
+ /* Account for difference in cost between indirect and direct calls. */
+ *size -= ((eni_size_weights.indirect_call_cost - eni_size_weights.call_cost)
+ * INLINE_SIZE_SCALE);
+ *time -= ((eni_time_weights.indirect_call_cost - eni_time_weights.call_cost)
+ * INLINE_TIME_SCALE * prob / REG_BR_PROB_BASE);
+
+ callee = cgraph_get_node (target);
+ if (!callee || !callee->analyzed)
+ return;
+ isummary = inline_summary (callee);
+ if (!isummary->inlinable)
+ return;
+
+ estimate_edge_size_and_time (ie, &edge_size, &edge_time, prob);
+
+ /* Count benefit only from functions that definitely will be inlined
+ if additional context from NODE's caller were available. */
+ if (edge_size >= isummary->size * INLINE_SIZE_SCALE)
+ {
+ /* Subtract size and time that we added for edge IE. */
+ *size -= edge_size;
+ *time -= edge_time;
+
+ /* Subtract benefit from inlining devirtualized call. */
+ *size -= edge_size - isummary->size * INLINE_SIZE_SCALE;
+ *time -= edge_time - (isummary->time * INLINE_TIME_SCALE * prob
+ / REG_BR_PROB_BASE);
+
+ /* TODO: estimate benefit from optimizing CALLEE's body provided
+ additional context from IE call site.
+ For insipiration see ipa-cp.c: devirtualization_time_bonus(). */
+ }
+}
+
+
+/* Increase SIZE and TIME for size and time needed to handle all calls in NODE.
+ POSSIBLE_TRUTHS, KNOWN_VALS and KNOWN_BINFOS describe context of the call
+ site. */
static void
estimate_calls_size_and_time (struct cgraph_node *node, int *size, int *time,
- clause_t possible_truths)
+ clause_t possible_truths,
+ VEC (tree, heap) *known_vals,
+ VEC (tree, heap) *known_binfos)
{
struct cgraph_edge *e;
for (e = node->callees; e; e = e->next_callee)
@@ -2189,25 +2272,32 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size, int *time,
}
else
estimate_calls_size_and_time (e->callee, size, time,
- possible_truths);
+ possible_truths,
+ known_vals, known_binfos);
}
}
- /* TODO: look for devirtualizing oppurtunities. */
for (e = node->indirect_calls; e; e = e->next_callee)
{
struct inline_edge_summary *es = inline_edge_summary (e);
if (!es->predicate || evaluate_predicate (es->predicate, possible_truths))
- estimate_edge_size_and_time (e, size, time, REG_BR_PROB_BASE);
+ {
+ estimate_edge_size_and_time (e, size, time, REG_BR_PROB_BASE);
+ estimate_edge_devirt_benefit (e, size, time, REG_BR_PROB_BASE,
+ known_vals, known_binfos);
+ }
}
}
/* Estimate size and time needed to execute NODE assuming
- POSSIBLE_TRUTHS clause. */
+ POSSIBLE_TRUTHS clause, and KNOWN_VALS and KNOWN_BINFOS information
+ about NODE's arguments. */
static void
estimate_node_size_and_time (struct cgraph_node *node,
clause_t possible_truths,
+ VEC (tree, heap) *known_vals,
+ VEC (tree, heap) *known_binfos,
int *ret_size, int *ret_time,
VEC (inline_param_summary_t, heap)
*inline_param_summary)
@@ -2258,7 +2348,8 @@ estimate_node_size_and_time (struct cgraph_node *node,
if (time > MAX_TIME * INLINE_TIME_SCALE)
time = MAX_TIME * INLINE_TIME_SCALE;
- estimate_calls_size_and_time (node, &size, &time, possible_truths);
+ estimate_calls_size_and_time (node, &size, &time, possible_truths,
+ known_vals, known_binfos);
time = (time + INLINE_TIME_SCALE / 2) / INLINE_TIME_SCALE;
size = (size + INLINE_SIZE_SCALE / 2) / INLINE_SIZE_SCALE;
@@ -2276,17 +2367,20 @@ estimate_node_size_and_time (struct cgraph_node *node,
/* Estimate size and time needed to execute callee of EDGE assuming that
parameters known to be constant at caller of EDGE are propagated.
- KNOWN_VALs is a vector of assumed known constant values for parameters. */
+ KNOWN_VALS and KNOWN_BINFOS are vectors of assumed known constant values
+ and types for parameters. */
void
estimate_ipcp_clone_size_and_time (struct cgraph_node *node,
VEC (tree, heap) *known_vals,
+ VEC (tree, heap) *known_binfos,
int *ret_size, int *ret_time)
{
clause_t clause;
clause = evaluate_conditions_for_known_args (node, false, known_vals);
- estimate_node_size_and_time (node, clause, ret_size, ret_time,
+ estimate_node_size_and_time (node, clause, known_vals, known_binfos,
+ ret_size, ret_time,
NULL);
}
@@ -2542,9 +2636,9 @@ inline_merge_summary (struct cgraph_edge *edge)
int count = ipa_get_cs_argument_count (args);
int i;
- clause = evaluate_conditions_for_edge (edge, true);
+ evaluate_properties_for_edge (edge, true, &clause, NULL, NULL);
if (count)
- VEC_safe_grow_cleared (int, heap, operand_map, count);
+ VEC_safe_grow_cleared (int, heap, operand_map, count);
for (i = 0; i < count; i++)
{
struct ipa_jump_func *jfunc = ipa_get_ith_jump_func (args, i);
@@ -2588,7 +2682,8 @@ inline_merge_summary (struct cgraph_edge *edge)
for (i = 0; VEC_iterate (size_time_entry, info->entry, i, e); i++)
info->size += e->size, info->time += e->time;
estimate_calls_size_and_time (to, &info->size, &info->time,
- ~(clause_t)(1 << predicate_false_condition));
+ ~(clause_t)(1 << predicate_false_condition),
+ NULL, NULL);
inline_update_callee_summaries (edge->callee,
inline_edge_summary (edge)->loop_depth);
@@ -2616,13 +2711,21 @@ do_estimate_edge_time (struct cgraph_edge *edge)
int time;
int size;
gcov_type ret;
+ struct cgraph_node *callee;
+ clause_t clause;
+ VEC (tree, heap) *known_vals;
+ VEC (tree, heap) *known_binfos;
struct inline_edge_summary *es = inline_edge_summary (edge);
+ callee = cgraph_function_or_thunk_node (edge->callee, NULL);
+
gcc_checking_assert (edge->inline_failed);
- estimate_node_size_and_time (cgraph_function_or_thunk_node (edge->callee,
- NULL),
- evaluate_conditions_for_edge (edge, true),
+ evaluate_properties_for_edge (edge, true,
+ &clause, &known_vals, &known_binfos);
+ estimate_node_size_and_time (callee, clause, known_vals, known_binfos,
&size, &time, es->param);
+ VEC_free (tree, heap, known_vals);
+ VEC_free (tree, heap, known_binfos);
ret = (((gcov_type)time
- es->call_stmt_time) * edge->frequency
@@ -2656,6 +2759,9 @@ do_estimate_edge_growth (struct cgraph_edge *edge)
{
int size;
struct cgraph_node *callee;
+ clause_t clause;
+ VEC (tree, heap) *known_vals;
+ VEC (tree, heap) *known_binfos;
/* When we do caching, use do_estimate_edge_time to populate the entry. */
@@ -2668,13 +2774,17 @@ do_estimate_edge_growth (struct cgraph_edge *edge)
gcc_checking_assert (size);
return size - (size > 0);
}
+
callee = cgraph_function_or_thunk_node (edge->callee, NULL);
/* Early inliner runs without caching, go ahead and do the dirty work. */
gcc_checking_assert (edge->inline_failed);
- estimate_node_size_and_time (callee,
- evaluate_conditions_for_edge (edge, true),
+ evaluate_properties_for_edge (edge, true,
+ &clause, &known_vals, &known_binfos);
+ estimate_node_size_and_time (callee, clause, known_vals, known_binfos,
&size, NULL, NULL);
+ VEC_free (tree, heap, known_vals);
+ VEC_free (tree, heap, known_binfos);
gcc_checking_assert (inline_edge_summary (edge)->call_stmt_size);
return size - inline_edge_summary (edge)->call_stmt_size;
}
diff --git a/gcc/ipa-inline.h b/gcc/ipa-inline.h
index 6df7867b019..a2c6cac0147 100644
--- a/gcc/ipa-inline.h
+++ b/gcc/ipa-inline.h
@@ -169,6 +169,7 @@ int estimate_time_after_inlining (struct cgraph_node *, struct cgraph_edge *);
int estimate_size_after_inlining (struct cgraph_node *, struct cgraph_edge *);
void estimate_ipcp_clone_size_and_time (struct cgraph_node *,
VEC (tree, heap) *known_vals,
+ VEC (tree, heap) *known_binfos,
int *, int *);
int do_estimate_growth (struct cgraph_node *);
void inline_merge_summary (struct cgraph_edge *edge);
diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
index 58caa92c305..1a609a5b5b7 100644
--- a/gcc/ipa-prop.h
+++ b/gcc/ipa-prop.h
@@ -346,6 +346,9 @@ bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
VEC (cgraph_edge_p, heap) **new_edges);
/* Indirect edge and binfo processing. */
+tree ipa_get_indirect_edge_target (struct cgraph_edge *ie,
+ VEC (tree, heap) *known_csts,
+ VEC (tree, heap) *known_binfs);
struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *, tree);
/* Functions related to both. */
@@ -437,8 +440,8 @@ void ipa_prop_write_jump_functions (cgraph_node_set set);
void ipa_prop_read_jump_functions (void);
void ipa_update_after_lto_read (void);
int ipa_get_param_decl_index (struct ipa_node_params *, tree);
-tree ipa_cst_from_jfunc (struct ipa_node_params *info,
- struct ipa_jump_func *jfunc);
+tree ipa_value_from_jfunc (struct ipa_node_params *info,
+ struct ipa_jump_func *jfunc);
/* From tree-sra.c: */
diff --git a/gcc/ira.c b/gcc/ira.c
index 008405cc35b..e335a701175 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -3621,9 +3621,8 @@ ira (FILE *f)
if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
fprintf (ira_dump_file, "Building IRA IR\n");
- loops_p = ira_build (optimize
- && (flag_ira_region == IRA_REGION_ALL
- || flag_ira_region == IRA_REGION_MIXED));
+ loops_p = ira_build (flag_ira_region == IRA_REGION_ALL
+ || flag_ira_region == IRA_REGION_MIXED);
ira_assert (ira_conflicts_p || !loops_p);
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 27a44f11f7d..e6d8db3a886 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,8 @@
+2011-11-23 Jeffrey A Law (law@cygnus.com)
+
+ * lang.c (java_init_options_struct): Disable optimizations
+ which assume a NULL pointer dereference will cause a fault.
+
2011-11-07 Richard Henderson <rth@redhat.com>
* builtins.c (compareAndSwapInt_builtin): Use can_compare_and_swap_p.
diff --git a/gcc/java/lang.c b/gcc/java/lang.c
index 6a117d79fcc..ccab48c4e7a 100644
--- a/gcc/java/lang.c
+++ b/gcc/java/lang.c
@@ -556,6 +556,10 @@ java_init_options_struct (struct gcc_options *opts)
/* Java requires left-to-right evaluation of subexpressions. */
opts->x_flag_evaluation_order = 1;
+
+ /* Java catches NULL pointer exceptions, thus we can not necessarily
+ rely on a pointer having a non-NULL value after a dereference. */
+ opts->x_flag_delete_null_pointer_checks = 0;
}
static void
diff --git a/gcc/jump.c b/gcc/jump.c
index f852f827729..52cbbca43db 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -1495,7 +1495,18 @@ redirect_jump (rtx jump, rtx nlabel, int delete_unused)
{
rtx olabel = JUMP_LABEL (jump);
- gcc_assert (nlabel != NULL_RTX);
+ if (!nlabel)
+ {
+ /* If there is no label, we are asked to redirect to the EXIT block.
+ When before the epilogue is emitted, return/simple_return cannot be
+ created so we return 0 immediately. After the epilogue is emitted,
+ we always expect a label, either a non-null label, or a
+ return/simple_return RTX. */
+
+ if (!epilogue_completed)
+ return 0;
+ gcc_unreachable ();
+ }
if (nlabel == olabel)
return 1;
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 98ae19b4aab..44a204977c0 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -522,6 +522,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
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);
+ bp_pack_value (&bp, node->tm_clone, 1);
bp_pack_value (&bp, node->thunk.thunk_p && !boundary_p, 1);
bp_pack_enum (&bp, ld_plugin_symbol_resolution,
LDPR_NUM_KNOWN, node->resolution);
@@ -928,6 +929,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
node->frequency = (enum node_frequency)bp_unpack_value (bp, 2);
node->only_called_at_startup = bp_unpack_value (bp, 1);
node->only_called_at_exit = bp_unpack_value (bp, 1);
+ node->tm_clone = bp_unpack_value (bp, 1);
node->thunk.thunk_p = bp_unpack_value (bp, 1);
node->resolution = bp_unpack_enum (bp, ld_plugin_symbol_resolution,
LDPR_NUM_KNOWN);
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index d8bbd9ca8dd..af849540ea8 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,8 @@
+2011-11-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * lto-lang.c (lto_attribute_table): Handle transaction_pure.
+ (handle_transaction_pure_attribute): New.
+
2011-11-03 Richard Guenther <rguenther@suse.de>
PR lto/44965
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index c702b9a2d24..2536f26ebf0 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -46,6 +46,7 @@ static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
+static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
static tree handle_format_attribute (tree *, tree, tree, int, bool *);
static tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
@@ -75,6 +76,8 @@ const struct attribute_spec lto_attribute_table[] =
handle_sentinel_attribute, false },
{ "type generic", 0, 0, false, true, true,
handle_type_generic_attribute, false },
+ { "transaction_pure", 0, 0, false, true, true,
+ handle_transaction_pure_attribute, false },
{ NULL, 0, 0, false, false, false, NULL, false }
};
@@ -402,6 +405,20 @@ handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
return NULL_TREE;
}
+/* Handle a "transaction_pure" attribute. */
+
+static tree
+handle_transaction_pure_attribute (tree *node, tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
+ bool * ARG_UNUSED (no_add_attrs))
+{
+ /* Ensure we have a function type. */
+ gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
+
+ return NULL_TREE;
+}
+
/* Handle a "format" attribute; arguments as in
struct attribute_spec.handler. */
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index a4bfb8413fe..4e1c2badae3 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -5501,7 +5501,9 @@ expand_omp_atomic (struct omp_region *region)
unsigned int align = TYPE_ALIGN_UNIT (type);
/* __sync builtins require strict data alignment. */
- if (exact_log2 (align) >= index)
+ /* ??? Assume BIGGEST_ALIGNMENT *is* aligned. */
+ if (exact_log2 (align) >= index
+ || align * BITS_PER_UNIT >= BIGGEST_ALIGNMENT)
{
/* Atomic load. */
if (loaded_val == stored_val
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 171756be7ef..a1917cc3220 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -6606,7 +6606,7 @@ init_sync_libfuncs_1 (optab tab, const char *base, int max)
buf[len + 2] = '\0';
mode = QImode;
- for (i = 1; i < max; i *= 2)
+ for (i = 1; i <= max; i *= 2)
{
buf[len + 1] = '0' + i;
set_optab_libfunc (tab, mode, buf);
@@ -6932,9 +6932,9 @@ can_vec_perm_for_code_p (enum tree_code code, enum machine_mode mode,
break;
case VEC_INTERLEAVE_HIGH_EXPR:
- alt = nelt / 2;
- /* FALLTHRU */
case VEC_INTERLEAVE_LOW_EXPR:
+ if ((BYTES_BIG_ENDIAN != 0) ^ (code == VEC_INTERLEAVE_HIGH_EXPR))
+ alt = nelt / 2;
for (i = 0; i < nelt / 2; ++i)
{
data[i * 2] = i + alt;
@@ -7325,17 +7325,12 @@ expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
}
-/* This function expands the atomic exchange operation:
- atomically store VAL in MEM and return the previous value in MEM.
-
- MEMMODEL is the memory model variant to use.
- TARGET is an optional place to stick the return value.
- USE_TEST_AND_SET indicates whether __sync_lock_test_and_set should be used
- as a fall back if the atomic_exchange pattern does not exist. */
-
-rtx
-expand_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model,
- bool use_test_and_set)
+/* This function tries to emit an atomic_exchange intruction. VAL is written
+ to *MEM using memory model MODEL. The previous contents of *MEM are returned,
+ using TARGET if possible. */
+
+static rtx
+maybe_emit_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model)
{
enum machine_mode mode = GET_MODE (mem);
enum insn_code icode;
@@ -7355,65 +7350,78 @@ expand_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model,
return ops[0].value;
}
- /* Legacy sync_lock_test_and_set works the same, but is only defined as an
- acquire barrier. If the pattern exists, and the memory model is stronger
- than acquire, add a release barrier before the instruction.
- The barrier is not needed if sync_lock_test_and_set doesn't exist since
- it will expand into a compare-and-swap loop.
+ return NULL_RTX;
+}
+
+/* This function tries to implement an atomic exchange operation using
+ __sync_lock_test_and_set. VAL is written to *MEM using memory model MODEL.
+ The previous contents of *MEM are returned, using TARGET if possible.
+ Since this instructionn is an acquire barrier only, stronger memory
+ models may require additional barriers to be emitted. */
+
+static rtx
+maybe_emit_sync_lock_test_and_set (rtx target, rtx mem, rtx val,
+ enum memmodel model)
+{
+ enum machine_mode mode = GET_MODE (mem);
+ enum insn_code icode;
+ rtx last_insn = get_last_insn ();
+
+ icode = optab_handler (sync_lock_test_and_set_optab, mode);
+
+ /* Legacy sync_lock_test_and_set is an acquire barrier. If the pattern
+ exists, and the memory model is stronger than acquire, add a release
+ barrier before the instruction. */
- Some targets have non-compliant test_and_sets, so it would be incorrect
- to emit a test_and_set in place of an __atomic_exchange. The test_and_set
- builtin shares this expander since exchange can always replace the
- test_and_set. */
+ if (model == MEMMODEL_SEQ_CST
+ || model == MEMMODEL_RELEASE
+ || model == MEMMODEL_ACQ_REL)
+ expand_mem_thread_fence (model);
- if (use_test_and_set)
+ if (icode != CODE_FOR_nothing)
{
- icode = optab_handler (sync_lock_test_and_set_optab, mode);
+ struct expand_operand ops[3];
+ create_output_operand (&ops[0], target, mode);
+ create_fixed_operand (&ops[1], mem);
+ /* VAL may have been promoted to a wider mode. Shrink it if so. */
+ create_convert_operand_to (&ops[2], val, mode, true);
+ if (maybe_expand_insn (icode, 3, ops))
+ return ops[0].value;
+ }
- if (icode != CODE_FOR_nothing)
+ /* If an external test-and-set libcall is provided, use that instead of
+ any external compare-and-swap that we might get from the compare-and-
+ swap-loop expansion later. */
+ if (!can_compare_and_swap_p (mode, false))
+ {
+ rtx libfunc = optab_libfunc (sync_lock_test_and_set_optab, mode);
+ if (libfunc != NULL)
{
- struct expand_operand ops[3];
- rtx last_insn = get_last_insn ();
-
- if (model == MEMMODEL_SEQ_CST
- || model == MEMMODEL_RELEASE
- || model == MEMMODEL_ACQ_REL)
- expand_builtin_mem_thread_fence (model);
-
- create_output_operand (&ops[0], target, mode);
- create_fixed_operand (&ops[1], mem);
- /* VAL may have been promoted to a wider mode. Shrink it if so. */
- create_convert_operand_to (&ops[2], val, mode, true);
- if (maybe_expand_insn (icode, 3, ops))
- return ops[0].value;
-
- delete_insns_since (last_insn);
+ rtx addr;
+
+ addr = convert_memory_address (ptr_mode, XEXP (mem, 0));
+ return emit_library_call_value (libfunc, target, LCT_NORMAL,
+ mode, 2, addr, ptr_mode,
+ val, mode);
}
+ }
- /* If an external test-and-set libcall is provided, use that instead of
- any external compare-and-swap that we might get from the compare-and-
- swap-loop expansion below. */
- if (!can_compare_and_swap_p (mode, false))
- {
- rtx libfunc = optab_libfunc (sync_lock_test_and_set_optab, mode);
- if (libfunc != NULL)
- {
- rtx addr;
+ /* If the test_and_set can't be emitted, eliminate any barrier that might
+ have been emitted. */
+ delete_insns_since (last_insn);
+ return NULL_RTX;
+}
- if (model == MEMMODEL_SEQ_CST
- || model == MEMMODEL_RELEASE
- || model == MEMMODEL_ACQ_REL)
- expand_builtin_mem_thread_fence (model);
+/* This function tries to implement an atomic exchange operation using a
+ compare_and_swap loop. VAL is written to *MEM. The previous contents of
+ *MEM are returned, using TARGET if possible. No memory model is required
+ since a compare_and_swap loop is seq-cst. */
- addr = convert_memory_address (ptr_mode, XEXP (mem, 0));
- return emit_library_call_value (libfunc, target, LCT_NORMAL,
- mode, 2, addr, ptr_mode,
- val, mode);
- }
- }
- }
+static rtx
+maybe_emit_compare_and_swap_exchange_loop (rtx target, rtx mem, rtx val)
+{
+ enum machine_mode mode = GET_MODE (mem);
- /* Otherwise, use a compare-and-swap loop for the exchange. */
if (can_compare_and_swap_p (mode, true))
{
if (!target || !register_operand (target, mode))
@@ -7427,6 +7435,105 @@ expand_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model,
return NULL_RTX;
}
+#ifndef HAVE_atomic_test_and_set
+#define HAVE_atomic_test_and_set 0
+#define gen_atomic_test_and_set(x,y,z) (gcc_unreachable (), NULL_RTX)
+#endif
+
+/* This function expands the legacy _sync_lock test_and_set operation which is
+ generally an atomic exchange. Some limited targets only allow the
+ constant 1 to be stored. This is an ACQUIRE operation.
+
+ TARGET is an optional place to stick the return value.
+ MEM is where VAL is stored. */
+
+rtx
+expand_sync_lock_test_and_set (rtx target, rtx mem, rtx val)
+{
+ rtx ret;
+
+ /* Try an atomic_exchange first. */
+ ret = maybe_emit_atomic_exchange (target, mem, val, MEMMODEL_ACQUIRE);
+
+ if (!ret)
+ ret = maybe_emit_sync_lock_test_and_set (target, mem, val,
+ MEMMODEL_ACQUIRE);
+ if (!ret)
+ ret = maybe_emit_compare_and_swap_exchange_loop (target, mem, val);
+
+ /* If there are no other options, try atomic_test_and_set if the value
+ being stored is 1. */
+ if (!ret && val == const1_rtx && HAVE_atomic_test_and_set)
+ {
+ ret = gen_atomic_test_and_set (target, mem, GEN_INT (MEMMODEL_ACQUIRE));
+ emit_insn (ret);
+ }
+
+ return ret;
+}
+
+/* This function expands the atomic test_and_set operation:
+ atomically store a boolean TRUE into MEM and return the previous value.
+
+ MEMMODEL is the memory model variant to use.
+ TARGET is an optional place to stick the return value. */
+
+rtx
+expand_atomic_test_and_set (rtx target, rtx mem, enum memmodel model)
+{
+ enum machine_mode mode = GET_MODE (mem);
+ rtx ret = NULL_RTX;
+
+ if (target == NULL_RTX)
+ target = gen_reg_rtx (mode);
+
+ if (HAVE_atomic_test_and_set)
+ {
+ ret = gen_atomic_test_and_set (target, mem, GEN_INT (MEMMODEL_ACQUIRE));
+ emit_insn (ret);
+ return ret;
+ }
+
+ /* If there is no test and set, try exchange, then a compare_and_swap loop,
+ then __sync_test_and_set. */
+ ret = maybe_emit_atomic_exchange (target, mem, const1_rtx, model);
+
+ if (!ret)
+ ret = maybe_emit_compare_and_swap_exchange_loop (target, mem, const1_rtx);
+
+ if (!ret)
+ ret = maybe_emit_sync_lock_test_and_set (target, mem, const1_rtx, model);
+
+ if (ret)
+ return ret;
+
+ /* Failing all else, assume a single threaded environment and simply perform
+ the operation. */
+ emit_move_insn (target, mem);
+ emit_move_insn (mem, const1_rtx);
+ return target;
+}
+
+/* This function expands the atomic exchange operation:
+ atomically store VAL in MEM and return the previous value in MEM.
+
+ MEMMODEL is the memory model variant to use.
+ TARGET is an optional place to stick the return value. */
+
+rtx
+expand_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model)
+{
+ rtx ret;
+
+ ret = maybe_emit_atomic_exchange (target, mem, val, model);
+
+ /* Next try a compare-and-swap loop for the exchange. */
+ if (!ret)
+ ret = maybe_emit_compare_and_swap_exchange_loop (target, mem, val);
+
+ return ret;
+}
+
/* This function expands the atomic compare exchange operation:
*PTARGET_BOOL is an optional place to store the boolean success/failure.
@@ -7556,6 +7663,76 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval,
return true;
}
+/* Generate asm volatile("" : : : "memory") as the memory barrier. */
+
+static void
+expand_asm_memory_barrier (void)
+{
+ rtx asm_op, clob;
+
+ asm_op = gen_rtx_ASM_OPERANDS (VOIDmode, empty_string, empty_string, 0,
+ rtvec_alloc (0), rtvec_alloc (0),
+ rtvec_alloc (0), UNKNOWN_LOCATION);
+ MEM_VOLATILE_P (asm_op) = 1;
+
+ clob = gen_rtx_SCRATCH (VOIDmode);
+ clob = gen_rtx_MEM (BLKmode, clob);
+ clob = gen_rtx_CLOBBER (VOIDmode, clob);
+
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, asm_op, clob)));
+}
+
+/* This routine will either emit the mem_thread_fence pattern or issue a
+ sync_synchronize to generate a fence for memory model MEMMODEL. */
+
+#ifndef HAVE_mem_thread_fence
+# define HAVE_mem_thread_fence 0
+# define gen_mem_thread_fence(x) (gcc_unreachable (), NULL_RTX)
+#endif
+#ifndef HAVE_memory_barrier
+# define HAVE_memory_barrier 0
+# define gen_memory_barrier() (gcc_unreachable (), NULL_RTX)
+#endif
+
+void
+expand_mem_thread_fence (enum memmodel model)
+{
+ if (HAVE_mem_thread_fence)
+ emit_insn (gen_mem_thread_fence (GEN_INT (model)));
+ else if (model != MEMMODEL_RELAXED)
+ {
+ if (HAVE_memory_barrier)
+ emit_insn (gen_memory_barrier ());
+ else if (synchronize_libfunc != NULL_RTX)
+ emit_library_call (synchronize_libfunc, LCT_NORMAL, VOIDmode, 0);
+ else
+ expand_asm_memory_barrier ();
+ }
+}
+
+/* This routine will either emit the mem_signal_fence pattern or issue a
+ sync_synchronize to generate a fence for memory model MEMMODEL. */
+
+#ifndef HAVE_mem_signal_fence
+# define HAVE_mem_signal_fence 0
+# define gen_mem_signal_fence(x) (gcc_unreachable (), NULL_RTX)
+#endif
+
+void
+expand_mem_signal_fence (enum memmodel model)
+{
+ if (HAVE_mem_signal_fence)
+ emit_insn (gen_mem_signal_fence (GEN_INT (model)));
+ else if (model != MEMMODEL_RELAXED)
+ {
+ /* By default targets are coherent between a thread and the signal
+ handler running on the same thread. Thus this really becomes a
+ compiler barrier, in that stores must not be sunk past
+ (or raised above) a given point. */
+ expand_asm_memory_barrier ();
+ }
+}
+
/* This function expands the atomic load operation:
return the atomically loaded value in MEM.
@@ -7598,13 +7775,13 @@ expand_atomic_load (rtx target, rtx mem, enum memmodel model)
target = gen_reg_rtx (mode);
/* Emit the appropriate barrier before the load. */
- expand_builtin_mem_thread_fence (model);
+ expand_mem_thread_fence (model);
emit_move_insn (target, mem);
/* For SEQ_CST, also emit a barrier after the load. */
if (model == MEMMODEL_SEQ_CST)
- expand_builtin_mem_thread_fence (model);
+ expand_mem_thread_fence (model);
return target;
}
@@ -7645,7 +7822,7 @@ expand_atomic_store (rtx mem, rtx val, enum memmodel model, bool use_release)
{
/* lock_release is only a release barrier. */
if (model == MEMMODEL_SEQ_CST)
- expand_builtin_mem_thread_fence (model);
+ expand_mem_thread_fence (model);
return const0_rtx;
}
}
@@ -7656,7 +7833,9 @@ expand_atomic_store (rtx mem, rtx val, enum memmodel model, bool use_release)
the result. If that doesn't work, don't do anything. */
if (GET_MODE_PRECISION(mode) > BITS_PER_WORD)
{
- rtx target = expand_atomic_exchange (NULL_RTX, mem, val, model, false);
+ rtx target = maybe_emit_atomic_exchange (NULL_RTX, mem, val, model);
+ if (!target)
+ target = maybe_emit_compare_and_swap_exchange_loop (NULL_RTX, mem, val);
if (target)
return const0_rtx;
else
@@ -7665,13 +7844,13 @@ expand_atomic_store (rtx mem, rtx val, enum memmodel model, bool use_release)
/* If there is no mem_store, default to a move with barriers */
if (model == MEMMODEL_SEQ_CST || model == MEMMODEL_RELEASE)
- expand_builtin_mem_thread_fence (model);
+ expand_mem_thread_fence (model);
emit_move_insn (mem, val);
/* For SEQ_CST, also emit a barrier after the load. */
if (model == MEMMODEL_SEQ_CST)
- expand_builtin_mem_thread_fence (model);
+ expand_mem_thread_fence (model);
return const0_rtx;
}
@@ -7889,7 +8068,7 @@ expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
{
/* If the result isn't used, no need to do compensation code. */
if (unused_result)
- return target;
+ return result;
/* Issue compensation code. Fetch_after == fetch_before OP val.
Fetch_before == after REVERSE_OP val. */
@@ -7931,9 +8110,7 @@ expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
result = emit_library_call_value (libfunc, NULL, LCT_NORMAL, mode,
2, addr, ptr_mode, val, mode);
- if (unused_result)
- return target;
- if (fixup)
+ if (!unused_result && fixup)
result = expand_simple_binop (mode, code, result, val, target,
true, OPTAB_LIB_WIDEN);
return result;
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 654d2766f40..ec13f6ff301 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -978,6 +978,10 @@ extern bool can_atomic_exchange_p (enum machine_mode, bool);
extern bool expand_atomic_compare_and_swap (rtx *, rtx *, rtx, rtx, rtx, bool,
enum memmodel, enum memmodel);
+/* Generate memory barriers. */
+extern void expand_mem_thread_fence (enum memmodel);
+extern void expand_mem_signal_fence (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 */
diff --git a/gcc/opts.c b/gcc/opts.c
index 9fdb22631d0..3153fe50274 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -784,8 +784,6 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
#endif
if (!opts->x_flag_fat_lto_objects && !HAVE_LTO_PLUGIN)
error_at (loc, "-fno-fat-lto-objects are supported only with linker plugin.");
- if (opts->x_flag_tm)
- error_at (loc, "LTO is currently not supported with transactional memory");
}
if ((opts->x_flag_lto_partition_balanced != 0) + (opts->x_flag_lto_partition_1to1 != 0)
+ (opts->x_flag_lto_partition_none != 0) >= 1)
diff --git a/gcc/output.h b/gcc/output.h
index e73c4a4c6bc..bc8c9d97825 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -129,7 +129,6 @@ typedef HOST_WIDE_INT __gcc_host_wide_int__;
#define ATTRIBUTE_ASM_FPRINTF(m, n) ATTRIBUTE_NONNULL(m)
#endif
-extern void fprint_w (FILE *, HOST_WIDE_INT);
extern void fprint_whex (FILE *, unsigned HOST_WIDE_INT);
extern void fprint_ul (FILE *, unsigned long);
extern int sprint_ul (char *, unsigned long);
@@ -639,6 +638,7 @@ extern section *default_elf_select_section (tree, int, unsigned HOST_WIDE_INT);
extern void default_unique_section (tree, int);
extern section *default_function_rodata_section (tree);
extern section *default_no_function_rodata_section (tree);
+extern section *default_clone_table_section (void);
extern section *default_select_rtx_section (enum machine_mode, rtx,
unsigned HOST_WIDE_INT);
extern section *default_elf_select_rtx_section (enum machine_mode, rtx,
diff --git a/gcc/postreload.c b/gcc/postreload.c
index 886d024926c..5c189129445 100644
--- a/gcc/postreload.c
+++ b/gcc/postreload.c
@@ -1312,11 +1312,21 @@ reload_combine (void)
is and then later disable any optimization that would cross it. */
if (LABEL_P (insn))
last_label_ruid = reload_combine_ruid;
- else if (BARRIER_P (insn)
- || (INSN_P (insn) && volatile_insn_p (PATTERN (insn))))
- for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
- if (! fixed_regs[r])
+ else if (BARRIER_P (insn))
+ {
+ /* Crossing a barrier resets all the use information. */
+ for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
+ if (! fixed_regs[r])
reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
+ }
+ else if (INSN_P (insn) && volatile_insn_p (PATTERN (insn)))
+ /* Optimizations across insns being marked as volatile must be
+ prevented. All the usage information is invalidated
+ here. */
+ for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
+ if (! fixed_regs[r]
+ && reg_state[r].use_index != RELOAD_COMBINE_MAX_USES)
+ reg_state[r].use_index = -1;
if (! NONDEBUG_INSN_P (insn))
continue;
diff --git a/gcc/recog.c b/gcc/recog.c
index 17cec759905..19f00b176d7 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -925,10 +925,7 @@ next_insn_tests_no_inequality (rtx insn)
it has.
The main use of this function is as a predicate in match_operand
- expressions in the machine description.
-
- For an explanation of this function's behavior for registers of
- class NO_REGS, see the comment for `register_operand'. */
+ expressions in the machine description. */
int
general_operand (rtx op, enum machine_mode mode)
@@ -998,9 +995,8 @@ general_operand (rtx op, enum machine_mode mode)
}
if (code == REG)
- /* A register whose class is NO_REGS is not a general operand. */
return (REGNO (op) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS (REGNO (op)) != NO_REGS);
+ || in_hard_reg_set_p (operand_reg_set, GET_MODE (op), REGNO (op)));
if (code == MEM)
{
@@ -1033,15 +1029,7 @@ address_operand (rtx op, enum machine_mode mode)
If MODE is VOIDmode, accept a register in any mode.
The main use of this function is as a predicate in match_operand
- expressions in the machine description.
-
- As a special exception, registers whose class is NO_REGS are
- not accepted by `register_operand'. The reason for this change
- is to allow the representation of special architecture artifacts
- (such as a condition code register) without extending the rtl
- definitions. Since registers of class NO_REGS cannot be used
- as registers in any case where register classes are examined,
- it is most consistent to keep this function from accepting them. */
+ expressions in the machine description. */
int
register_operand (rtx op, enum machine_mode mode)
@@ -1080,11 +1068,10 @@ register_operand (rtx op, enum machine_mode mode)
op = sub;
}
- /* We don't consider registers whose class is NO_REGS
- to be a register operand. */
return (REG_P (op)
&& (REGNO (op) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
+ || in_hard_reg_set_p (operand_reg_set,
+ GET_MODE (op), REGNO (op))));
}
/* Return 1 for a register in Pmode; ignore the tested mode. */
@@ -1203,11 +1190,10 @@ nonmemory_operand (rtx op, enum machine_mode mode)
op = SUBREG_REG (op);
}
- /* We don't consider registers whose class is NO_REGS
- to be a register operand. */
return (REG_P (op)
&& (REGNO (op) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
+ || in_hard_reg_set_p (operand_reg_set,
+ GET_MODE (op), REGNO (op))));
}
/* Return 1 if OP is a valid operand that stands for pushing a
diff --git a/gcc/reginfo.c b/gcc/reginfo.c
index e9bf65f3003..f6f91a9975b 100644
--- a/gcc/reginfo.c
+++ b/gcc/reginfo.c
@@ -192,6 +192,9 @@ init_reg_sets (void)
memcpy (reg_alloc_order, initial_reg_alloc_order, sizeof reg_alloc_order);
#endif
memcpy (reg_names, initial_reg_names, sizeof reg_names);
+
+ SET_HARD_REG_SET (accessible_reg_set);
+ SET_HARD_REG_SET (operand_reg_set);
}
/* Initialize may_move_cost and friends for mode M. */
@@ -292,6 +295,8 @@ static char saved_call_used_regs[FIRST_PSEUDO_REGISTER];
static char saved_call_really_used_regs[FIRST_PSEUDO_REGISTER];
#endif
static const char *saved_reg_names[FIRST_PSEUDO_REGISTER];
+static HARD_REG_SET saved_accessible_reg_set;
+static HARD_REG_SET saved_operand_reg_set;
/* Save the register information. */
void
@@ -315,6 +320,8 @@ save_register_info (void)
/* And similarly for reg_names. */
gcc_assert (sizeof reg_names == sizeof saved_reg_names);
memcpy (saved_reg_names, reg_names, sizeof reg_names);
+ COPY_HARD_REG_SET (saved_accessible_reg_set, accessible_reg_set);
+ COPY_HARD_REG_SET (saved_operand_reg_set, operand_reg_set);
}
/* Restore the register information. */
@@ -330,6 +337,8 @@ restore_register_info (void)
#endif
memcpy (reg_names, saved_reg_names, sizeof reg_names);
+ COPY_HARD_REG_SET (accessible_reg_set, saved_accessible_reg_set);
+ COPY_HARD_REG_SET (operand_reg_set, saved_operand_reg_set);
}
/* After switches have been processed, which perhaps alter
@@ -459,8 +468,27 @@ init_reg_sets_1 (void)
else
CLEAR_REG_SET (fixed_reg_set_regset);
+ AND_HARD_REG_SET (operand_reg_set, accessible_reg_set);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
+ /* As a special exception, registers whose class is NO_REGS are
+ not accepted by `register_operand'. The reason for this change
+ is to allow the representation of special architecture artifacts
+ (such as a condition code register) without extending the rtl
+ definitions. Since registers of class NO_REGS cannot be used
+ as registers in any case where register classes are examined,
+ it is better to apply this exception in a target-independent way. */
+ if (REGNO_REG_CLASS (i) == NO_REGS)
+ CLEAR_HARD_REG_BIT (operand_reg_set, i);
+
+ /* If a register is too limited to be treated as a register operand,
+ then it should never be allocated to a pseudo. */
+ if (!TEST_HARD_REG_BIT (operand_reg_set, i))
+ {
+ fixed_regs[i] = 1;
+ call_used_regs[i] = 1;
+ }
+
/* call_used_regs must include fixed_regs. */
gcc_assert (!fixed_regs[i] || call_used_regs[i]);
#ifdef CALL_REALLY_USED_REGISTERS
diff --git a/gcc/reorg.c b/gcc/reorg.c
index 40d73a76a71..0b90550add5 100644
--- a/gcc/reorg.c
+++ b/gcc/reorg.c
@@ -3600,9 +3600,11 @@ relax_delay_slots (rtx first)
}
}
+ /* See if we have a simple (conditional) jump that is useless. */
if (! INSN_ANNULLED_BRANCH_P (delay_insn)
- && prev_active_insn (target_label) == insn
&& ! condjump_in_parallel_p (delay_insn)
+ && prev_active_insn (target_label) == insn
+ && ! BARRIER_P (prev_nonnote_insn (target_label))
#ifdef HAVE_cc0
/* If the last insn in the delay slot sets CC0 for some insn,
various code assumes that it is in a delay slot. We could
diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c
index a778721d20b..043204a34bc 100644
--- a/gcc/sched-deps.c
+++ b/gcc/sched-deps.c
@@ -2812,8 +2812,14 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
during prologue generation and avoid marking the frame pointer setup
as frame-related at all. */
if (RTX_FRAME_RELATED_P (insn))
- deps->sched_before_next_jump
- = alloc_INSN_LIST (insn, deps->sched_before_next_jump);
+ {
+ /* Make sure prologue insn is scheduled before next jump. */
+ deps->sched_before_next_jump
+ = alloc_INSN_LIST (insn, deps->sched_before_next_jump);
+
+ /* Make sure epilogue insn is scheduled after preceding jumps. */
+ add_dependence_list (insn, deps->pending_jump_insns, 1, REG_DEP_ANTI);
+ }
if (code == COND_EXEC)
{
diff --git a/gcc/target.def b/gcc/target.def
index 62bd06e976f..f5a5d54904a 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -305,6 +305,13 @@ section names for mergeable constant data. Define this macro to override\n\
the string if a different section name should be used.",
const char *, ".rodata")
+/* Return the section to be used for transactional memory clone tables. */
+DEFHOOK
+(tm_clone_table_section,
+ "Return the section that should be used for transactional memory clone\
+ tables.",
+ section *, (void), default_clone_table_section)
+
/* Output a constructor for a symbol with a given priority. */
DEFHOOK
(constructor,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 57e5eb57ea5..a6a077c9b88 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,568 @@
+2011-11-28 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/51308
+ * gfortran.dg/iso_c_binding_compiler_4.f90: New.
+
+2011-11-27 Aldy Hernandez <aldyh@redhat.com>
+ Iain Sandoe <iains@gcc.gnu.org>
+
+ * gcc.dg/lto/trans-mem-2_0.c: Add dg-lto-do link. Add dummy
+ functions for _ITM_registerTMCloneTable, _ITM_deregisterTMCloneTable.
+ * gcc.dg/lto/trans-mem-1_0.c: Add dg-lto-do link.
+ * gcc.dg/lto/trans-mem-1_1.c: Add dummy functions for
+ _ITM_registerTMCloneTable, _ITM_deregisterTMCloneTable.
+
+2011-11-27 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * gcc.target/mips/mult-2.c, gcc.target/mips/mult-3.c,
+ gcc.target/mips/mult-4.c, gcc.target/mips/mult-5.c,
+ gcc.target/mips/mult-6.c, gcc.target/mips/mult-7.c,
+ gcc.target/mips/mult-8.c, gcc.target/mips/mult-9.c,
+ gcc.target/mips/mult-10.c, gcc.target/mips/mult-11.c,
+ gcc.target/mips/mult-12.c, gcc.target/mips/mult-13.c,
+ gcc.target/mips/mult-14.c, gcc.target/mips/mult-15.c,
+ gcc.target/mips/mult-16.c, gcc.target/mips/mult-17.c,
+ gcc.target/mips/mult-18.c, gcc.target/mips/mult-19.c,
+ gcc.target/mips/div-1.c, gcc.target/mips/div-2.c,
+ gcc.target/mips/div-3.c, gcc.target/mips/div-4.c,
+ gcc.target/mips/div-5.c, gcc.target/mips/div-6.c,
+ gcc.target/mips/div-7.c, gcc.target/mips/div-8.c,
+ gcc.target/mips/div-9.c, gcc.target/mips/div-10.c,
+ gcc.target/mips/div-11.c, gcc.target/mips/div-12.c: New tests.
+ * gcc.target/mips/fix-r4000-1.c (foo, bar): Add NOMIPS16.
+ * gcc.target/mips/fix-r4000-2.c (foo): Likewise.
+ * gcc.target/mips/fix-r4000-3.c (foo): Likewise.
+ * gcc.target/mips/fix-r4000-4.c (foo): Likewise.
+ * gcc.target/mips/fix-r4000-5.c (foo): Likewise.
+ * gcc.target/mips/fix-r4000-6.c (foo): Likewise.
+ * gcc.target/mips/fix-r4000-7.c (foo): Likewise.
+ * gcc.target/mips/fix-r4000-8.c (foo): Likewise.
+ * gcc.target/mips/fix-r4000-9.c (foo): Likewise.
+ * gcc.target/mips/fix-r4000-10.c (foo): Likewise.
+ * gcc.target/mips/fix-r4000-11.c (foo): Likewise.
+ * gcc.target/mips/fix-r4000-12.c (foo): Likewise.
+
+2011-11-27 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * gcc.target/mips/mips.exp (mips-dg-options): Make -mno-dsp
+ imply -mno-dspr2.
+ * gcc.target/mips/no-dsp-1.c: New test.
+ * gcc.target/mips/soft-float-1.c: Likewise.
+
+2011-11-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/49912
+ * g++.dg/other/pr49912.C: New test.
+
+2011-11-26 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.dg/vect/fast-math-vect-call-2.c: Require vect_double
+ effective target.
+ * gcc.dg/vect/fast-math-bb-slp-call-2.c: Ditto.
+
+2011-11-25 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/51250
+ PR fortran/43829
+ * gfortran.dg/inline_sum_3.f90: New test.
+
+2011-11-25 Uros Bizjak <ubizjak@gmail.com>
+
+ PR testsuite/51258
+ * lib/target-supports.exp
+ (check_effective_target_sync_long_long): Also supported on 32bit
+ x86 targets. Add comment about required dg-options.
+ Add alpha*-*-* targets.
+ (check_effective_target_sync_long_long_runtime): Ditto.
+
+ * gcc.dg/atomic-op-4.c (dg-options): Add -march=pentium for
+ 32bit x86 targets.
+ * gcc.dg/atomic-compare-exchange-4.c: Ditto.
+ * gcc.dg/atomic-exchange-4.c: Ditto.
+ * gcc.dg/atomic-load-4.c: Ditto.
+ * gcc.dg/atomic-store-4.c: Ditto.
+ * gcc.dg/di-longlong64-sync-1.c: Ditto.
+ * gcc.dg/di-sync-multithread.c: Ditto.
+ * gcc.dg/simulate-thread/atomic-load-longlong.c: Ditto.
+ * gcc.dg/simulate-thread/atomic-other-longlong.c: Ditto.
+
+2011-11-25 Uros Bizjak <ubizjak@gmail.com>
+
+ PR testsuite/51258
+ * lib/target-supports.exp
+ (check_effective_target_sync_int_128_runtime): New procedure.
+ (check_effective_target_sync_long_long_runtime): Ditto.
+ (check_effective_target_sync_long_long): Add arm*-*-*.
+ (check_effective_target_sync_longlong): Remove.
+
+ * gcc.dg/atomic-op-5.c: Require sync_int_128_runtime effective target.
+ * gcc.dg/atomic-compare-exchange-5.c: Ditto.
+ * gcc.dg/atomic-exchange-5.c: Ditto.
+ * gcc.dg/atomic-load-5.c: Ditto.
+ * gcc.dg/atomic-store-5.c: Ditto.
+ * gcc.dg/simulate-thread/atomic-load-int128.c: Ditto.
+ * gcc.dg/simulate-thread/atomic-other-int128.c: Ditto.
+ * gcc.dg/atomic-op-4.c: Require sync_long_long_runtime
+ effective target.
+ * gcc.dg/atomic-compare-exchange-4.c: Ditto.
+ * gcc.dg/atomic-exchange-4.c: Ditto.
+ * gcc.dg/atomic-load-4.c: Ditto.
+ * gcc.dg/atomic-store-4.c: Ditto.
+ * gcc.dg/di-longlong64-sync-1.c: Ditto.
+ * gcc.dg/di-sync-multithread.c: Ditto.
+ * gcc.dg/simulate-thread/atomic-load-longlong.c: Ditto.
+ * gcc.dg/simulate-thread/atomic-other-longlong.c: Ditto.
+
+2011-11-25 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/50408
+ * gfortran.dg/whole_file_35.f90: New.
+
+2011-11-25 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/51302
+ * gfortran.dg/volatile13.f90: New.
+
+2011-11-24 Andrew MacLeod <amacleod@redhat.com>
+
+ PR c/51256
+ * gcc.dg/atomic-pr51256.c: New. Test error conditions.
+
+2011-11-24 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51227
+ * g++.dg/cpp0x/lambda/lambda-ice5.C: New.
+
+2011-11-24 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/51134
+ * gcc.target/i386/sw-1.c: Revert revision 181357.
+
+2011-11-24 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/51218
+ * gfortran.dg/implicit_pure_1.f90: New.
+
+2011-11-24 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ PR testsuite/51258
+ * gcc.dg/atomic-compare-exchange-5.c: Add -mcx16 on i?86-*-*.
+ * gcc.dg/atomic-exchange-5.c: Likewise.
+ * gcc.dg/atomic-load-5.c: Likewise.
+ * gcc.dg/atomic-op-5.c: Likewise.
+ * gcc.dg/atomic-store-5.c: Likewise.
+ * gcc.dg/simulate-thread/atomic-other-int128.c: Fix typo.
+
+2011-11-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/50290
+ * gcc.dg/pr50290.c: New test.
+
+2011-11-24 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51290
+ * g++.dg/warn/Wzero-as-null-pointer-constant-3.C: New.
+
+2011-11-23 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/51261
+ * gcc.dg/pr51261.c: New test.
+
+2011-11-22 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/51145
+ * g++.dg/cpp0x/alias-decl-14.C: New test.
+ * g++.dg/cpp0x/alias-decl-2.C: Adjust for tests that were wrongly
+ passing before.
+ * g++.dg/cpp0x/alias-decl-10.C: Likewise and adjust for diagnostic
+ change.
+ * g++.dg/ext/attrib27.C: Adjust for diagnostic change.
+ * g++.dg/lookup/struct1.C: Likewise.
+ * g++.dg/parse/elab1.C: Likewise.
+ * g++.dg/parse/elab2.C: Likewise.
+ * g++.dg/parse/int-as-enum1.C: Likewise.
+ * g++.dg/parse/typedef1.C: Likewise.
+ * g++.dg/parse/typedef3.C: Likewise.
+ * g++.dg/parse/typedef4.C: Likewise.
+ * g++.dg/parse/typedef5.C: Likewise.
+ * g++.dg/template/crash26.C: Likewise.
+ * g++.dg/template/nontype4.C: Likewise.
+ * g++.old-deja/g++.benjamin/typedef01.C: Likewise.
+ * g++.old-deja/g++.brendan/line1.C: Likewise.
+ * g++.old-deja/g++.other/elab1.C: Likewise.
+ * g++.old-deja/g++.other/syntax4.C: Likewise.
+
+2011-11-22 Tom de Vries <tom@codesourcery.com>
+
+ PR rtl-optimization/50764
+ * gcc.dg/pr50764.c: New test.
+
+2011-11-22 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51265
+ * g++.dg/cpp0x/decltype36.C: New.
+
+2011-11-22 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/51074
+ * gcc.dg/vect/pr51074.c: New test.
+
+2011-11-22 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/51143
+ * g++.dg/cpp0x/alias-decl-16.C: New test.
+
+2011-11-22 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/50765
+ * gcc.dg/pr50765.c: New test.
+
+2011-11-22 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
+
+ * gcc.dg/vshift-1.c (main): Call rand instead of random.
+ * gcc.dg/vshift-3.c (main): Likewise.
+
+2011-11-22 Iain Sandoe <iains@gcc.gnu.org>
+
+ * gcc.dg/tm/20100615.c: Adjust for Darwin tm_clone_table section name.
+
+2011-11-22 Iain Sandoe <iains@gcc.gnu.org>
+
+ * gcc.misc-tests/gcov-16.c: Adjust scan-assembler for Darwin.
+ * gcc.misc-tests/gcov-17.c: Likewise.
+ * g++.dg/gcov/gcov-8.C: Likewise.
+ * g++.dg/gcov/gcov-9.C: Likewise.
+
+2011-11-21 Torvald Riegel <triegel@redhat.com>
+
+ * g++.dg/tm/pr47747.C: New test.
+
+2011-11-21 Torvald Riegel <triegel@redhat.com>
+
+ * g++.dg/tm/template-2.C: New test.
+
+2011-11-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/50827
+ * gcc.dg/pr50827.c: New test.
+
+2011-11-21 Ed Smith-Rowland <3dw4rd@verizon.net>
+
+ PR c++/50958
+ * g++.dg/cpp0x/udlit-declare-neg.C: Adjust.
+ * g++.dg/cpp0x/udlit-implicit-conv-neg.C: New.
+ * g++.dg/cpp0x/udlit-member.C: Adjust.
+ * g++.dg/cpp0x/udlit-raw-length.C: New.
+ * g++.dg/cpp0x/udlit-raw-op-string-neg.C: Adjust.
+ * g++.dg/cpp0x/udlit-resolve.C: New.
+ * c-c++-common/dfp/pr33466.c: Adjust.
+
+2011-11-21 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * lib/target-supports.exp
+ (check_effective_target_ultrasparc_vis2_hw): Call check_runtime
+ with ultrasparc_vis2_hw.
+ (check_effective_target_ultrasparc_vis3_hw): Call check_runtime
+ with ultrasparc_vis3_hw.
+
+2011-11-21 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * c-c++-common/tm/malloc.c: Scan tree dumps for std::malloc if
+ *-*-solaris2* && c++.
+
+2011-11-20 Joey Ye <joey.ye@arm.com>
+
+ * gcc.dg/volatile-bitfields-1.c: New.
+
+2011-11-20 Jason Merrill <jason@redhat.com>
+
+ PR c++/48322
+ * g++.dg/cpp0x/variadic120.C: New.
+ * g++.dg/cpp0x/sfinae26.C: Adjust.
+
+ * g++.dg/cpp0x/sfinae11.C: Adjust.
+ * g++.dg/cpp0x/sfinae26.C: Adjust.
+ * g++.dg/template/unify11.C: Adjust.
+
+2011-11-20 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51230
+ * g++.dg/template/error46.C: New.
+
+2011-11-20 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/51235
+ * gcc.target/i386/pr51235.c: New test.
+
+ PR target/51236
+ * gcc.target/i386/pr51236.c: New test.
+
+2011-11-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/discr32.adb: New test.
+ * gnat.dg/discr32_pkg.ads: New helper.
+
+2011-11-20 Nathan Sidwell <nathan@acm.org>
+
+ PR gcov-profile/51113
+ * gcc.misc-tests/gcov-13.c: Check gcovpart-13b coverage
+ * gcc.misc-tests/gcov-16.c: New.
+ * gcc.misc-tests/gcov-17.c: New.
+ * g++.dg/gcov/gcov-8.C: New.
+ * g++.dg/gcov/gcov-9.C: New.
+ * g++.dg/gcov/gcov-10.C: New.
+
+2011-11-20 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/51194
+ * g++.dg/cpp0x/alias-decl-15.C: New test.
+
+2011-11-19 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51216
+ * g++.dg/cpp0x/pr51216.C: New.
+
+2011-11-19 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/delay-slot-2.c: New test.
+
+2011-11-18 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/cpp/assert4.c: Test __linux__, not __gnu_linux__.
+
+2011-11-18 Fabien Chêne <fabien@gcc.gnu.org>
+
+ PR c++/51188
+ * g++.dg/lookup/using46.C: New.
+ * g++.dg/lookup/using47.C: New.
+ * g++.dg/lookup/using48.C: New.
+ * g++.dg/lookup/using49.C: New.
+ * g++.dg/lookup/using50.C: New.
+
+2011-11-18 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * gcc.c-torture/compile/pr44707.c: Do not assume assembler
+ supports /* ... */ comments.
+
+2011-11-18 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51150
+ * g++.dg/cpp0x/pr51150.C: New.
+
+2011-11-18 Martin Jambor <mjambor@suse.cz>
+
+ PR tree-optimization/50605
+ * g++.dg/ipa/pr50605.C: New test.
+
+2011-11-18 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/51191
+ * g++.dg/cpp0x/alias-decl-13.C: New test.
+
+2011-11-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/51186
+ * g++.dg/cpp0x/auto27.C: New.
+ * g++.dg/cpp0x/trailing2.C: Adjust messages.
+
+2011-11-17 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/atomic-generic-aux.c (__atomic_compare_exchange): Fail if
+ memory model parameters don't match expected values.
+ * gcc.dg/atomic-generic.c: Pass specific memory model parameters to
+ __atomic_compare_exchange.
+ * gcc.dg/atomic-noinline.c: Pass specific memory model parameters to
+ __atomic_compare_exchange_n.
+ * gcc.dg/atomic-noinline-aux.c (__atomic_compare_exchange_2): Remove
+ weak/strong parameter and fail if memory models aren't correct.
+
+2011-10-17 Uros Bizjak <ubizjak@gmail.com>
+
+ * lib/gcc-simulate-thread.exp (simulate-thread): Run on all targets.
+ Look for simulate_thread_done to determine working gdb. Reduce timeout
+ to 10 seconds and fail when timeout occurs. Improve error messages.
+
+2011-11-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/51137
+ * g++.dg/template/virtual2.C: New.
+
+2011-11-17 Michael Matz <matz@suse.de>
+
+ PR middle-end/50644
+ PR middle-end/50741
+ * g++.dg/tree-ssa/pr50741.C: New.
+
+2011-11-17 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * lib/gcc-simulate-thread.exp (simulate-thread): Skip on alpha*-*-*.
+
+2011-10-16 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.dg/tm/memopt-6.c: Cleanup tmedge tree dump.
+ * gcc.dg/tm/memopt-13.c: Cleanup tmmark tree dump.
+ * g++.dg/eh/array1.C: Cleanup gimple tree dump.
+
+2011-11-16 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/39427
+ PR fortran/37829
+ * gfortran.dg/constructor_1.f90: New.
+ * gfortran.dg/constructor_2.f90: New.
+ * gfortran.dg/constructor_3.f90: New.
+ * gfortran.dg/constructor_4.f90: New.
+ * gfortran.dg/constructor_5.f90: New.
+ * gfortran.dg/constructor_6.f90: New.
+ * gfortran.dg/use_only_5.f90: New.
+ * gfortran.dg/c_ptr_tests_17.f90: New.
+ * gfortran.dg/c_ptr_tests_18.f90: New.
+ * gfortran.dg/used_types_25.f90: New.
+ * gfortran.dg/used_types_26.f90: New
+ * gfortran.dg/type_decl_3.f90: New.
+ * gfortran.dg/function_types_3.f90: Update dg-error.
+ * gfortran.dg/result_1.f90: Ditto.
+ * gfortran.dg/structure_constructor_3.f03: Ditto.
+ * gfortran.dg/structure_constructor_4.f03: Ditto.
+
+2011-10-16 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
+
+ * gcc.dg/vect/pr30858.c: Update expected output for
+ architectures with multiple vector sizes.
+
+2011-11-16 Richard Earnshaw <rearnsha@arm.com>
+ Bernd Schmidt <bernds@coudesourcery.com>
+ Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ PR target/49641
+ * gcc.target/arm/pr49641.c: New test.
+
+2011-11-16 Razya Ladelsky <razya@il.ibm.com>
+
+ PR tree-optimization/49960
+ * gcc.dg/autopar/pr49960.c: New test.
+ * gcc.dg/autopar/pr49960-1.c: New test.
+
+
+2011-11-16 Tom de Vries <tom@codesourcery.com>
+
+ * gcc.dg/pr43864.c: Check for absence of 'Invalid sum' in pre tree-dump.
+ * gcc.dg/pr43864-2.c: Same.
+ * gcc.dg/pr43864-3.c: Same.
+ * gcc.dg/pr43864-4.c: Same.
+
+2011-11-15 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/sse2-cvt-vec.c: New test.
+ * gcc.target/i386/avx-cvt-vec.c: Ditto.
+ * gcc.target/i386/avx-cvt-2-vec.c: Ditto.
+ * gcc.target/i386/avx-floor-sfix-2-vec.c: Ditto.
+ * gcc.target/i386/avx-ceil-sfix-2-vec.c: Ditto.
+ * gcc.target/i386/avx-rint-sfix-2-vec.c: Ditto.
+ * gcc.target/i386/avx-round-sfix-2-vec.c: Ditto.
+
+2011-11-15 Iain Sandoe <iains@gcc.gnu.org>
+
+ * lib/gcc-simulate-thread.exp (simulate-thread): Do not run on
+ powerpc*-*-darwin* targets.
+
+2011-11-15 Torvald Riegel <triegel@redhat.com>
+
+ * c-c++-common/tm/trxn-expr-3.c: New test.
+
+2011-11-14 Torvald Riegel <triegel@redhat.com>
+
+ * g++.dg/tm/template-1.C: Add cleanup-tree-dump. Fix typo in comment.
+
+2011-11-14 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/avx-recip-vec.c: New test.
+ * gcc.target/i386/avx-lrintf-vec.c: Ditto.
+ * gcc.target/i386/avx-lrint-vec.c: Ditto.
+ * gcc.target/i386/avx-floorf-vec.c: Include sse4_1-floorf-vec.c.
+ * gcc.target/i386/avx-floor-vec.c: Include sse4_1-floor-vec.c.
+ * gcc.target/i386/avx-ceilf-vec.c: Include sse4_1-ceilf-vec.c.
+ * gcc.target/i386/avx-ceil-vec.c: Include sse4_1-ceil-vec.c.
+ * gcc.target/i386/avx-rintf-vec.c: Include sse4_1-rintf-vec.c.
+ * gcc.target/i386/avx-rint-vec.c: Include sse4_1-rint-vec.c.
+ * gcc.target/i386/avx-roundf-vec.c: Include sse4_1-roundf-vec.c.
+ * gcc.target/i386/avx-round-vec.c: Include sse4_1-round-vec.c.
+ * gcc.target/i386/avx-truncf-vec.c: Include sse4_1-truncf-vec.c.
+ * gcc.target/i386/avx-trunc-vec.c: Include sse4_1-trunc-vec.c.
+ * gcc.target/i386/avx-copysignf-vec.c: Include sse-copysignf-vec.c.
+ * gcc.target/i386/avx-copysign-vec.c: Include sse2-copysign-vec.c.
+
+2011-11-14 Ed Smith-Rowland <3dw4rd@verizon.net>
+
+ PR c++/51107
+ * g++.dg/cpp0x/udlit-args-neg.C: Add check for void argument
+ non-template literal operator.
+
+2011-11-14 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/sse4_1-floor-sfix-vec.c: New test.
+ * gcc.target/i386/sse4_1-floorf-sfix-vec.c: Ditto.
+ * gcc.target/i386/avx-floor-sfix-vec.c: Ditto.
+ * gcc.target/i386/avx-floorf-sfix-vec.c: Ditto.
+ * gcc.target/i386/sse4_1-ceil-sfix-vec.c: Ditto.
+ * gcc.target/i386/sse4_1-ceilf-sfix-vec.c: Ditto.
+ * gcc.target/i386/avx-ceil-sfix-vec.c: Ditto.
+ * gcc.target/i386/avx-ceilf-sfix-vec.c: Ditto.
+ * gcc.target/i386/sse4_1-rint-sfix-vec.c: Ditto.
+ * gcc.target/i386/sse4_1-rintf-sfix-vec.c: Ditto.
+ * gcc.target/i386/avx-rint-sfix-vec.c: Ditto.
+ * gcc.target/i386/avx-rintf-sfix-vec.c: Ditto.
+ * gcc.target/i386/sse4_1-round-sfix-vec.c: Ditto.
+ * gcc.target/i386/sse4_1-roundf-sfix-vec.c: Ditto.
+ * gcc.target/i386/avx-round-sfix-vec.c: Ditto.
+ * gcc.target/i386/avx-roundf-sfix-vec.c: Ditto.
+
+2011-11-14 Fabien Chêne <fabien@gcc.gnu.org>
+
+ PR c++/6936
+ PR c++/25994
+ PR c++/26256
+ PR c++/30195
+ * g++.old-deja/g++.brendan/misc14.C: Adjust.
+ * g++.old-deja/g++.jason/scoping16.C: Likewise.
+ * g++.old-deja/g++.other/anon7.C: Likewise.
+ * g++.old-deja/g++.other/using1.C: Likewise.
+ * g++.old-deja/g++.other/redecl1.C: Likewise.
+ * g++.old-deja/g++.other/typedef7.C: Likewise.
+ * g++.old-deja/g++.bugs/900127_02.C: Likewise.
+ * g++.dg/template/using2.C: Likewise.
+ * g++.dg/template/static4.C: Likewise.
+ * g++.dg/template/typedef1.C: Likewise.
+ * g++.dg/lookup/name-clash9.C: Likewise.
+ * g++.dg/abi/mangle41.C: Likewise.
+ * g++.dg/parse/ctor5.C: Likewise.
+ * g++.dg/inherit/using4.C: Likewise.
+ * g++.dg/lookup/using24.C: New.
+ * g++.dg/lookup/using25.C: New.
+ * g++.dg/lookup/using26.C: New.
+ * g++.dg/lookup/using27.C: New.
+ * g++.dg/lookup/using28.C: New.
+ * g++.dg/lookup/using29.C: New.
+ * g++.dg/lookup/using30.C: New.
+ * g++.dg/lookup/using31.C: New.
+ * g++.dg/lookup/using32.C: New.
+ * g++.dg/lookup/using33.C: New.
+ * g++.dg/lookup/using34.C: New.
+ * g++.dg/lookup/using35.C: New.
+ * g++.dg/lookup/using36.C: New.
+ * g++.dg/lookup/using37.C: New.
+ * g++.dg/lookup/using38.C: New.
+ * g++.dg/lookup/using39.C: New.
+ * g++.dg/lookup/using40.C: New.
+ * g++.dg/lookup/using41.C: New.
+ * g++.dg/lookup/using42.C: New.
+ * g++.dg/lookup/using43.C: New.
+ * g++.dg/lookup/using44.C: New.
+ * g++.dg/lookup/using45.C: New.
+ * g++.dg/lookup/pr6936.C: New.
+ * g++.dg/debug/using4.C: New.
+ * g++.dg/debug/using5.C: New.
+ * g++.dg/cpp0x/forw_enum10.C: New.
+
2011-11-14 Zolotukhin Michael <michael.v.zolotukhin@gmail.com>
Jan Hubicka <jh@suse.cz>
@@ -262,8 +827,8 @@
2011-11-09 Janne Blomqvist <jb@gcc.gnu.org>
- PR libfortran/50016
- * gfortran.dg/inquire_size.f90: Don't flush the unit.
+ PR libfortran/50016
+ * gfortran.dg/inquire_size.f90: Don't flush the unit.
2011-11-09 Richard Guenther <rguenther@suse.de>
@@ -448,8 +1013,8 @@
2011-11-07 Janne Blomqvist <jb@gcc.gnu.org>
- PR libfortran/45723
- * gfortran.dg/open_dev_null.f90: Remove testcase.
+ PR libfortran/45723
+ * gfortran.dg/open_dev_null.f90: Remove testcase.
2011-11-07 Uros Bizjak <ubizjak@gmail.com>
diff --git a/gcc/testsuite/c-c++-common/dfp/pr33466.c b/gcc/testsuite/c-c++-common/dfp/pr33466.c
index 8c73cef4856..9b10a092b91 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|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" } */
+long double dF = 4.5dF; /* { dg-error "invalid suffix|literal operator" } */
+long double Df = 4.5Df; /* { dg-error "invalid suffix|literal operator" } */
+long double dD = 4.5dD; /* { dg-error "invalid suffix|literal operator" } */
+long double Dd = 4.5Dd; /* { dg-error "invalid suffix|literal operator" } */
+long double dL = 4.5dL; /* { dg-error "invalid suffix|literal operator" } */
+long double Dl = 4.5Dl; /* { dg-error "invalid suffix|literal operator" } */
diff --git a/gcc/testsuite/c-c++-common/tm/malloc.c b/gcc/testsuite/c-c++-common/tm/malloc.c
index de7a766e36c..81bcc56fc41 100644
--- a/gcc/testsuite/c-c++-common/tm/malloc.c
+++ b/gcc/testsuite/c-c++-common/tm/malloc.c
@@ -17,7 +17,9 @@ void foobar(void)
z = (char *)malloc (666);
}
-/* { dg-final { scan-tree-dump-times " malloc .666" 1 "tmmark" } } */
+/* { dg-final { scan-tree-dump-times " malloc .666" 1 "tmmark" { target { ! { *-*-solaris2* && c++ } } } } } */
+/* Solaris 2 headers are C++-aware and declare std::malloc. */
+/* { dg-final { scan-tree-dump-times " std::malloc .666" 1 "tmmark" { target { *-*-solaris2* && c++ } } } } */
/* { dg-final { scan-tree-dump-times "__builtin__ITM_malloc" 1 "tmmark" } } */
/* { dg-final { scan-tree-dump-times "__builtin__ITM_calloc" 1 "tmmark" } } */
/* { dg-final { scan-tree-dump-times "__builtin__ITM_free" 2 "tmmark" } } */
diff --git a/gcc/testsuite/c-c++-common/tm/trxn-expr-3.c b/gcc/testsuite/c-c++-common/tm/trxn-expr-3.c
new file mode 100644
index 00000000000..0a87780f17e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/tm/trxn-expr-3.c
@@ -0,0 +1,14 @@
+// { dg-do compile }
+// { dg-options "-fgnu-tm -O -fdump-tree-tmmark" }
+
+int global;
+
+int f2()
+{
+ return __transaction_atomic (global + 3)
+ + __transaction_atomic (global + 4);
+}
+
+/* { dg-final { scan-tree-dump-times "ITM_RU" 2 "tmmark" } } */
+/* { dg-final { scan-tree-dump-times "ITM_commitTransaction" 2 "tmmark" } } */
+/* { dg-final { cleanup-tree-dump "tmmark" } } */
diff --git a/gcc/testsuite/g++.dg/abi/mangle41.C b/gcc/testsuite/g++.dg/abi/mangle41.C
index 3a9c04f77d0..4c0d0038e80 100644
--- a/gcc/testsuite/g++.dg/abi/mangle41.C
+++ b/gcc/testsuite/g++.dg/abi/mangle41.C
@@ -3,5 +3,6 @@
// { dg-options "-mavx -fabi-version=2" }
#include <x86intrin.h>
-void f(__m128) { } // { dg-error "previous" }
-void f(__m256) { } // { dg-message "declaration|mangling" }
+void f(__m128) { } // { dg-message "previous declaration" }
+void f(__m256) { } // { dg-error "conflicts" }
+// { dg-message "mangling" "" { target *-*-* } 7 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C
index 856e4297af5..733e791c2bc 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C
@@ -3,16 +3,24 @@
template <class T> using Ptr = T*;
Ptr<unsigned>; // { dg-error "does not declare anything" }
Ptr<char><int>; // { dg-error "not a template|does not declare anything" }
-template class Ptr<int>;//{ dg-error "explicit instantiation|non-class templ|does not decl|anything" }
+template class Ptr<int>;//{ dg-error "alias template specialization\[^\n\r\]*after\[^\n\r\]*class" }
template <class T> using Arg = T;
struct A {};
-template class Arg<A>;// { dg-error "explicit instantiation|non-class templ" }
+template class Arg<A>;// { dg-error "alias templ\[^\n\r\]*specialization\[^\n\r\]*Arg<A>\[^\n\r\]*after\[^\n\r\]*class" }
template <template <class> class TT, class T> using Instantiate = TT<T>;
template <class> struct Vector {};
-template class Instantiate<Vector, int>; // OK Vector<int> can be explicitely instantiated
+
+// The below is not OK, because of [dcl.type.elab]:
+//
+// If the identifier resolves to a typedef-name or the
+// simple-template-id resolves to an alias template
+// specialization, the elaborated-type-specifier is ill-formed.
+//
+template class Instantiate<Vector, int>;//{ dg-error "alias template specialization\[^\n\r\]*after\[^\n\r\]*class" }
template <class T> struct S {};
template<class T> using SFor = S<T>;
-template class SFor<int>; // OK, S<int> can be explicitely instantiated
+// Likewise, this is not OK.
+template class SFor<int>; //{ dg-error "alias template specialization\[^\n\r\]*after\[^\n\r\]*class" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-13.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-13.C
new file mode 100644
index 00000000000..8555154c634
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-13.C
@@ -0,0 +1,24 @@
+// Origin PR c++/51191
+// { dg-options "-std=c++0x" }
+
+template< class T >
+class ClassTemplate {};
+
+template< class T >
+struct Metafunction {
+ typedef T type;
+};
+
+template< class T >
+using TemplateAlias = ClassTemplate< typename Metafunction<T>::type >;
+
+using Alias = TemplateAlias<int>;
+
+template< class T >
+void f( TemplateAlias<T> );
+
+int main()
+{
+ Alias x;
+ f( x ); // { dg-error "no matching function for call to|f" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C
new file mode 100644
index 00000000000..1a998022adc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C
@@ -0,0 +1,14 @@
+// Origin: PR c++/51145
+// { dg-options "-std=c++0x" }
+
+struct A {};
+
+template<class>
+using X = A;
+
+struct X<int>* px; // { dg-error "using\[^\n\r\]*alias\[^\n\r\]*specialization\[^\n\r\]*X<int>\[^\n\r\]*after\[^\n\r\]*struct|invalid type in declaration before\[^\n\r\]*;" }
+
+template<int>
+using Y = A;
+
+struct Y<0>* py;// { dg-error "alias\[^\n\r\]*specialization\[^\n\r\]*Y<0>\[^\n\r\]*after\[^\n\r\]*struct|invalid type in declaration before\[^\n\r\]*;" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-15.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-15.C
new file mode 100644
index 00000000000..2bc9b11843d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-15.C
@@ -0,0 +1,17 @@
+// Origin PR c++/51194
+// { dg-options "-std=c++0x" }
+
+template<class U, class V> //#1
+struct foo {}; // { dg-error "provided for|foo" }
+
+template<class U, class V=char>
+struct P {};
+
+template<template<class... U> class... TT>
+struct bar {
+ template<class... Args>
+ using mem = P<TT<Args...>...>;//#2 { dg-error "wrong number of|arguments" }
+};
+
+bar<foo>::mem<int, char> b;//#3 { dg-error "invalid type" }
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-16.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-16.C
new file mode 100644
index 00000000000..d66660a5f4e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-16.C
@@ -0,0 +1,28 @@
+// Origin PR c++/51143
+// { dg-options "-std=c++11" }
+
+using A0 = struct B0 { void f() {} };
+
+template<int N>
+using A1 =
+ struct B1 { // { dg-error "types may not be defined in alias template" }
+ static auto constexpr value = N;
+ };
+
+A1<0> a1;
+
+template<class T>
+using A2 =
+ struct B2 { // { dg-error "types may not be defined in alias template" }
+ void f(T){}
+ };
+
+A2<bool> a2;
+
+template<class T>
+using A3 =
+ enum B3 {b = 0;}; //{ dg-error "types may not be defined in alias template" }
+
+A3<int> a3;
+
+int main() { }
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C
index 2e03dd897b5..6b5b42f7fde 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C
@@ -6,7 +6,7 @@ template<class T> using AS0 = S0<T>;
template<template<class> class TT>
void f(TT<int>);
-template class AS0<char>;
+template class AS0<char>; // { dg-error "alias templ\[^\n\r\]*specialization\[^\n\r\]*after\[^\n\r\]*class" }
void
foo()
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto27.C b/gcc/testsuite/g++.dg/cpp0x/auto27.C
new file mode 100644
index 00000000000..c1041df54b0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/auto27.C
@@ -0,0 +1,6 @@
+// PR c++/51186
+
+auto main()->int // { dg-error "std=" "" { target c++98 } }
+ // { dg-error "auto" "" { target c++98 } 3 }
+ // { dg-error "no type" "" { target c++98 } 3 }
+{ }
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype36.C b/gcc/testsuite/g++.dg/cpp0x/decltype36.C
new file mode 100644
index 00000000000..f3dfed992cf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype36.C
@@ -0,0 +1,21 @@
+// PR c++/51265
+// { dg-options -std=c++0x }
+
+struct Funny
+{
+ int print(int);
+};
+
+template<typename X>
+void c();
+
+template<typename X, X ff>
+void xx()
+{
+ c<decltype(ff)>();
+}
+
+int main()
+{
+ xx<int(Funny::*)(int), &Funny::print>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum10.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum10.C
new file mode 100644
index 00000000000..a57c0a9f415
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum10.C
@@ -0,0 +1,31 @@
+// { dg-do compile }
+// { dg-options "-std=c++0x" }
+
+//This error is diagnosed at instantiation time
+template<typename T> struct S1
+{
+ enum E : T; // { dg-error "previous definition" }
+ enum E : int; // { dg-error "different underlying type" }
+};
+template struct S1<short>; // { dg-message "required from here" }
+
+template<typename T> struct S2
+{
+ enum E : T;
+ enum E : T;
+};
+template struct S2<short>;
+
+template<typename T1, typename T2> struct S3
+{
+ enum E : T1;
+ enum E : T2;
+};
+template struct S3<short,short>;
+
+template<typename T1, typename T2> struct S4
+{
+ enum E : T1; // { dg-error "previous definition" }
+ enum E : T2; // { dg-error "different underlying type" }
+};
+template struct S4<short,char>; // { dg-message "required from here" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice5.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice5.C
new file mode 100644
index 00000000000..305db812d82
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice5.C
@@ -0,0 +1,12 @@
+// PR c++/51227
+// { dg-options "-std=c++0x" }
+
+template<int> int foo()
+{
+ [] (void i) { return 0; } (0); // { dg-error "incomplete|invalid|no match" }
+}
+
+void bar()
+{
+ foo<0>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr51150.C b/gcc/testsuite/g++.dg/cpp0x/pr51150.C
new file mode 100644
index 00000000000..37eb166b43e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr51150.C
@@ -0,0 +1,20 @@
+// PR c++/51150
+// { dg-options "-std=c++0x" }
+
+struct Clock {
+ double Now();
+};
+template <class T> void Foo(Clock* clock) {
+ const int now = clock->Now();
+}
+
+template void Foo<float>(Clock*);
+
+template <class T> void Boo(int val) {
+ const int now1 = (double)(val);
+ const int now2 = const_cast<double>(val); // { dg-error "invalid" }
+ const int now3 = static_cast<double>(val);
+ const int now4 = reinterpret_cast<double>(val); // { dg-error "invalid" }
+}
+
+template void Boo<float>(int);
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr51216.C b/gcc/testsuite/g++.dg/cpp0x/pr51216.C
new file mode 100644
index 00000000000..4bdd071475e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr51216.C
@@ -0,0 +1,10 @@
+// PR c++/51216
+// { dg-options "-std=c++0x" }
+
+void foo()
+{
+ int i = ({ if (1) ; }); // { dg-error "ignored" }
+ int j = ({ for (;;) ; }); // { dg-error "ignored" }
+ int k = ({ while (1) ; }); // { dg-error "ignored" }
+ int l = ({ do { } while (1); }); // { dg-error "ignored" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae11.C b/gcc/testsuite/g++.dg/cpp0x/sfinae11.C
index 25902cbd65e..2e8408d8f4d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae11.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae11.C
@@ -12,7 +12,8 @@ inline void f1( T& x ) noexcept( noexcept( declval<T&>().foo() ) ) // { dg-error
}
template< class T,
- bool Noexcept = noexcept( declval<T&>().foo() )
+ bool Noexcept = noexcept( declval<T&>().foo() ) // { dg-error "no member|not convert" }
+
>
inline void f2( T& x ) noexcept( Noexcept )
{
@@ -51,7 +52,6 @@ int main()
// static_assert( noexcept( f3(y) ), "shall be ill-formed(OK)." );
noexcept( f1(z) ); // { dg-message "required" }
- static_assert( noexcept( f2(z) ), "shall be ill-formed." ); // { dg-error "no match|could not convert" }
- // { dg-error "no member" "" { target *-*-* } 54 }
+ static_assert( noexcept( f2(z) ), "shall be ill-formed." ); // { dg-error "no match" }
noexcept( f3(z) ); // { dg-message "required" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae26.C b/gcc/testsuite/g++.dg/cpp0x/sfinae26.C
index 42b48eb5a6b..374f9976b2c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae26.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae26.C
@@ -30,9 +30,9 @@ struct is_same<T, T> {
template<class... T>
struct S {
template<class... U,
- typename enable_if<and_<is_same<T, U>...>::value>::type*& = enabler
+ typename enable_if<and_<is_same<T, U>...>::value>::type*& = enabler // { dg-error "no type" }
>
- S(U...){} // { dg-error "no type named 'type'" }
+ S(U...){}
};
S<bool> s(0); // { dg-error "no match" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae30.C b/gcc/testsuite/g++.dg/cpp0x/sfinae30.C
new file mode 100644
index 00000000000..6fcf5f75609
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae30.C
@@ -0,0 +1,25 @@
+// { dg-do compile { target c++11 } }
+
+template <class... T> struct tuple;
+template <class T> struct tuple<T> { T t; };
+
+template <class T, class U> struct pair;
+template<> struct pair<int,double> { };
+
+template <class... Ts>
+struct A
+{
+ template <class... Us,
+ class V = tuple<pair<Ts,Us>...> >
+ static void f(Us...)
+ {
+ V v;
+ }
+ template <class U>
+ static void f(bool);
+};
+
+int main()
+{
+ A<int,float>::f<double>(1.0);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing2.C b/gcc/testsuite/g++.dg/cpp0x/trailing2.C
index e45204fe715..5f5af22947f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/trailing2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/trailing2.C
@@ -3,14 +3,14 @@
// { dg-options "-std=c++0x" }
auto f1 () -> int;
-auto f2 (); // { dg-error "without late return type" }
-int f3 () -> int; // { dg-error "late return type" }
-auto *f4 () -> int; // { dg-error "late return type" }
+auto f2 (); // { dg-error "without trailing return type" }
+int f3 () -> int; // { dg-error "trailing return type" }
+auto *f4 () -> int; // { dg-error "trailing return type" }
struct A
{
auto f5 () const -> int;
- auto f6 (); // { dg-error "without late return type" }
- int f7 () -> int; // { dg-error "late return type" }
- auto *f8 () -> int; // { dg-error "late return type" }
+ auto f6 (); // { dg-error "without trailing return type" }
+ int f7 () -> int; // { dg-error "trailing return type" }
+ auto *f8 () -> int; // { dg-error "trailing return type" }
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-args-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-args-neg.C
index cb924a249bf..df7b7281c3d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-args-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-args-neg.C
@@ -4,6 +4,9 @@
class Foo { };
+int
+operator"" _Foo(); // { dg-error "has invalid argument list" }
+
Foo
operator"" _Foo(int *); // { dg-error "has invalid argument list" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C
index 7b50c017f01..9060abba494 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C
@@ -3,13 +3,13 @@
// 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 j = 'x'_Bar; // { dg-error "unable to find character literal operator|with|argument" }
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" }
+int jj = "Howdy, Pardner!"_BarCharStr; // { dg-error "unable to find string literal operator|Possible missing length argument" }
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" }
+unsigned long long jULL = 666_BarULL; // { dg-error "unable to find 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" }
+long double jLD = 666.0_BarLD; // { dg-error "unable to find numeric literal operator" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-implicit-conv-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-implicit-conv-neg.C
new file mode 100644
index 00000000000..998ad155bf7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-implicit-conv-neg.C
@@ -0,0 +1,63 @@
+// { dg-options -std=c++0x }
+
+#include <cstdint>
+
+int operator"" _bar (long double);
+
+double operator"" _foo (long long unsigned);
+
+int i = 12_bar; // { dg-error "unable to find numeric literal operator|with|argument" }
+
+double d = 1.2_foo; // { dg-error "unable to find numeric literal operator|with|argument" }
+
+int operator"" _char(char);
+
+int operator"" _wchar_t(wchar_t);
+
+int operator"" _char16_t(char16_t);
+
+int operator"" _char32_t(char32_t);
+
+int cwcx = 'c'_wchar_t; // { dg-error "unable to find character literal operator|with|argument" }
+int cc16 = 'c'_char16_t; // { dg-error "unable to find character literal operator|with|argument" }
+int cc32 = 'c'_char32_t; // { dg-error "unable to find character literal operator|with|argument" }
+
+int wccx = L'c'_char; // { dg-error "unable to find character literal operator|with|argument" }
+int wcc16 = L'c'_char16_t; // { dg-error "unable to find character literal operator|with|argument" }
+int wcc32 = L'c'_char32_t; // { dg-error "unable to find character literal operator|with|argument" }
+
+int c16c = u'c'_char; // { dg-error "unable to find character literal operator|with|argument" }
+int c16wc = u'c'_wchar_t; // { dg-error "unable to find character literal operator|with|argument" }
+int c16c32 = u'c'_char32_t; // { dg-error "unable to find character literal operator|with|argument" }
+
+int c32c = U'c'_char; // { dg-error "unable to find character literal operator|with|argument" }
+int c32wc = U'c'_wchar_t; // { dg-error "unable to find character literal operator|with|argument" }
+int c32c16 = U'c'_char16_t; // { dg-error "unable to find character literal operator|with|argument" }
+
+int operator"" _char_str(const char*, std::size_t);
+
+int operator"" _wchar_t_str(const wchar_t*, std::size_t);
+
+int operator"" _char16_t_str(const char16_t*, std::size_t);
+
+int operator"" _char32_t_str(const char32_t*, std::size_t);
+
+int strwstr = "str"_wchar_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int strstr16 = "str"_char16_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int strstr32 = "str"_char32_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+
+int str8wstr = u8"str"_wchar_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str8str16 = u8"str"_char16_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str8str32 = u8"str"_char32_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+
+int wstrstr = L"str"_char_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int wstrstr16 = L"str"_char16_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int wstrstr32 = L"str"_char32_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+
+int str16str = u"str"_char_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str16wstr = u"str"_wchar_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str16str32 = u"str"_char32_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+
+int str32str = U"str"_char_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str32wstr = U"str"_wchar_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str32str16 = U"str"_char16_t_str; // { dg-error "unable to find string literal operator string operator|with|arguments" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C
index 809df254c0e..a6220c4c0fc 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C
@@ -8,7 +8,7 @@ public:
};
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 j = U'x'_Bar; // { dg-error "unable to find character literal operator" }
int
Foo::operator"" _Bar(char32_t) // { dg-error "must be a non-member function" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-length.C b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-length.C
new file mode 100644
index 00000000000..2d910624a7c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-length.C
@@ -0,0 +1,27 @@
+// { dg-options "-std=c++0x" }
+// PR c++/50958
+
+typedef decltype(sizeof(0)) size_type;
+
+constexpr size_type
+cstrlen_impl(const char* s, size_type i)
+{
+ return s[i] ? cstrlen_impl(s, i + 1) : i;
+}
+
+constexpr size_type
+cstrlen(const char* s)
+{
+ return s ? cstrlen_impl(s, 0) : throw 0;
+}
+
+constexpr size_type
+operator "" _lenraw(const char* digits)
+{
+ return cstrlen(digits);
+}
+
+static_assert(123_lenraw == 3, "Ouch");
+static_assert(1_lenraw == 1, "Ouch");
+static_assert(012_lenraw == 3, "Ouch");
+static_assert(0_lenraw == 1, "Ouch");
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
index 5c399aff599..58ad0e609d0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op-string-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op-string-neg.C
@@ -5,4 +5,4 @@
int operator"" _embedraw(const char*)
{ return 41; };
-int k = "Boo!"_embedraw; // { dg-error "unable to find valid user-defined string literal operator" }
+int k = "Boo!"_embedraw; // { dg-error "unable to find string literal operator" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C b/gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C
new file mode 100644
index 00000000000..a25516220c2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C
@@ -0,0 +1,40 @@
+// { dg-do run }
+// { dg-options "-std=c++0x" }
+
+#include <cstdint>
+#include <cassert>
+
+int operator"" _foo(const char*) { return 0; }
+int operator"" _foo(unsigned long long int) { return 1; }
+int operator"" _foo(long double) { return 2; }
+int operator"" _foo(char) { return 3; }
+int operator"" _foo(wchar_t) { return 4; }
+int operator"" _foo(char16_t) { return 5; }
+int operator"" _foo(char32_t) { return 6; }
+int operator"" _foo(const char*, std::size_t) { return 7; }
+int operator"" _foo(const wchar_t*, std::size_t) { return 8; }
+int operator"" _foo(const char16_t*, std::size_t) { return 9; }
+int operator"" _foo(const char32_t*, std::size_t) { return 10; }
+template<char...> int operator"" _foo2() { return 20; }
+int operator"" _foo2(unsigned long long int) { return 21; }
+
+namespace bar {
+int operator"" _foo(unsigned long long int) { return 101; }
+}
+using namespace bar;
+
+int
+main()
+{
+ assert(123_foo == 101);
+ assert(0.123_foo == 2);
+ assert('c'_foo == 3);
+ assert(L'c'_foo == 4);
+ assert(u'c'_foo == 5);
+ assert(U'c'_foo == 6);
+ assert("abc"_foo == 7);
+ assert(L"abc"_foo == 8);
+ assert(u"abc"_foo == 9);
+ assert(U"abc"_foo == 10);
+ assert(123_foo2 == 21);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic120.C b/gcc/testsuite/g++.dg/cpp0x/variadic120.C
new file mode 100644
index 00000000000..e26ee4e9abe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic120.C
@@ -0,0 +1,24 @@
+// PR c++/48322
+// { dg-do compile { target c++11 } }
+
+template <class... T> struct tuple;
+template <class T> struct tuple<T> { T t; };
+
+template <class T, class U> struct pair;
+template<> struct pair<int,double> { };
+
+template <class... Ts>
+struct A
+{
+ template <class... Us,
+ class V = tuple<pair<Ts,Us>...> >
+ static void f()
+ {
+ V v;
+ }
+};
+
+int main()
+{
+ A<int>::f<double>();
+}
diff --git a/gcc/testsuite/g++.dg/debug/using4.C b/gcc/testsuite/g++.dg/debug/using4.C
new file mode 100644
index 00000000000..8a6162606c4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/using4.C
@@ -0,0 +1,24 @@
+// PR c++/26256
+// { dg-do compile }
+
+struct A
+{
+ typedef char type;
+};
+
+struct B
+{
+ typedef int type;
+};
+
+struct C : A, B
+{
+ using A::type;
+ type f (type);
+};
+
+C::type C::f( type )
+{
+ type c = 'e';
+ return c;
+}
diff --git a/gcc/testsuite/g++.dg/debug/using5.C b/gcc/testsuite/g++.dg/debug/using5.C
new file mode 100644
index 00000000000..3f2de9bfb80
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/using5.C
@@ -0,0 +1,23 @@
+// PR c++/26256
+// { dg-do compile }
+
+struct A
+{
+ int i;
+};
+
+struct B
+{
+ int i;
+};
+
+struct C : A, B
+{
+ using B::i;
+ int f ();
+};
+
+int C::f()
+{
+ return i;
+}
diff --git a/gcc/testsuite/g++.dg/debug/using6.C b/gcc/testsuite/g++.dg/debug/using6.C
new file mode 100644
index 00000000000..8f73d37ffa0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/using6.C
@@ -0,0 +1,22 @@
+// PR c++/51189
+// { dg-do compile }
+
+struct A
+{
+ int i1, i2, i3, i4, i5, i6;
+};
+
+struct B : A
+{
+ using A::i1;
+ using A::i2;
+ using A::i3;
+ using A::i4;
+ using A::i5;
+ using A::i6;
+};
+
+struct C : B
+{
+ using B::i1;
+};
diff --git a/gcc/testsuite/g++.dg/eh/array1.C b/gcc/testsuite/g++.dg/eh/array1.C
index 157450a9592..43e5bc02449 100644
--- a/gcc/testsuite/g++.dg/eh/array1.C
+++ b/gcc/testsuite/g++.dg/eh/array1.C
@@ -1,7 +1,6 @@
// Test that we have one EH cleanup region for the whole array
// rather than one for each element.
-// { dg-options -fdump-tree-gimple }
-// { dg-final { scan-tree-dump-times "catch" 1 "gimple" } }
+// { dg-options "-fdump-tree-gimple" }
struct A
{
@@ -13,3 +12,6 @@ void f()
{
A a[10] = { };
}
+
+// { dg-final { scan-tree-dump-times "catch" 1 "gimple" } }
+// { dg-final { cleanup-tree-dump "gimple" } }
diff --git a/gcc/testsuite/g++.dg/ext/attrib27.C b/gcc/testsuite/g++.dg/ext/attrib27.C
index 4f629aa5372..b770c1c4404 100644
--- a/gcc/testsuite/g++.dg/ext/attrib27.C
+++ b/gcc/testsuite/g++.dg/ext/attrib27.C
@@ -1,5 +1,5 @@
//PR c++/29980
-struct A { typedef int X; }; // { dg-error "previous declaration" }
+struct A { typedef int X; }; // { dg-message "previous declaration" }
struct __attribute__((unused)) A::X; // { dg-error "typedef-name" }
diff --git a/gcc/testsuite/g++.dg/gcov/gcov-10.C b/gcc/testsuite/g++.dg/gcov/gcov-10.C
new file mode 100644
index 00000000000..4c91be94ee4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gcov/gcov-10.C
@@ -0,0 +1,20 @@
+/* Ensure PIC sequence used for comdat functions */
+
+/* { dg-options "-fprofile-arcs -ftest-coverage -fpic" } */
+/* { dg-do run { target native } } */
+/* { dg-require-effective-target fpic } */
+
+inline int __attribute__ ((noinline)) Foo ()
+{
+ static int x[1];
+
+ return x[0]++; /* count (1) */
+}
+
+int main ()
+{
+ Foo (); /* count (1) */
+ return 0; /* count (1) */
+}
+
+/* { dg-final { run-gcov gcov-10.C } } */
diff --git a/gcc/testsuite/g++.dg/gcov/gcov-11.C b/gcc/testsuite/g++.dg/gcov/gcov-11.C
new file mode 100644
index 00000000000..fa0890206f3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gcov/gcov-11.C
@@ -0,0 +1,42 @@
+/* Check that unexecuted exception processing regions are shown
+ distinct from unexecuted normal regions. */
+
+/* { dg-options "-fprofile-arcs -ftest-coverage" } */
+/* { dg-do run { target native } } */
+
+void Baz (int i)
+{
+ if (i)
+ throw 1;
+}
+
+void Boz () throw ()
+{
+}
+
+int main ()
+{
+ try
+ {
+ Baz (0); /* count (1) */
+ Baz (0); /* count (1) */
+ }
+ catch (...)
+ {
+ Boz (); /* count (=====) */
+ }
+
+ try
+ {
+ Baz (1); /* count (1) */
+ Baz (0); /* count (#####) */
+ }
+ catch (...)
+ {
+ Boz (); /* count (1) */
+ }
+
+ return 0; /* count (1) */
+}
+
+/* { dg-final { run-gcov gcov-11.C } } */
diff --git a/gcc/testsuite/g++.dg/gcov/gcov-8.C b/gcc/testsuite/g++.dg/gcov/gcov-8.C
new file mode 100644
index 00000000000..272cefc373b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gcov/gcov-8.C
@@ -0,0 +1,14 @@
+/* { dg-options "-fprofile-arcs -fvisibility=hidden" } */
+/* { dg-require-visibility "" } */
+
+struct __attribute__((visibility ("hidden"))) X
+{
+ void Fink ();
+};
+
+void X::Fink ()
+{
+}
+
+/* { dg-final { scan-assembler "\\.hidden\t__gcov___ZN1X4FinkEv" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "\\.private_extern ___gcov___ZN1X4FinkEv" { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/g++.dg/gcov/gcov-9.C b/gcc/testsuite/g++.dg/gcov/gcov-9.C
new file mode 100644
index 00000000000..b9c64d22e56
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gcov/gcov-9.C
@@ -0,0 +1,17 @@
+/* { dg-options "-fprofile-arcs -fvisibility-inlines-hidden" } */
+/* { dg-require-visibility "" } */
+
+inline void Boo ()
+{
+}
+
+extern "C" void (*Foo ()) ()
+{
+ return Boo;
+}
+
+/* { dg-final { scan-assembler "\\.hidden\t__gcov___Z3Boov" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "\\.private_extern ___gcov___Z3Boov" { target *-*-darwin* } } } */
+/* { dg-final { scan-assembler "__gcov__Foo:" } } */
+/* { dg-final { scan-assembler-not "\\.hidden\t__gcov__Foo" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler-not "\\.private_extern ___gcov__Foo" { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/g++.dg/inherit/using4.C b/gcc/testsuite/g++.dg/inherit/using4.C
index a0b38737e1e..4b7a28f0f46 100644
--- a/gcc/testsuite/g++.dg/inherit/using4.C
+++ b/gcc/testsuite/g++.dg/inherit/using4.C
@@ -9,6 +9,6 @@ struct B {
};
struct D : B {
- using B::f;
- using B::f; // { dg-error "repeated" }
+ using B::f; // { dg-message "previous declaration" }
+ using B::f; // { dg-error "redeclaration" }
};
diff --git a/gcc/testsuite/g++.dg/ipa/pr50605.C b/gcc/testsuite/g++.dg/ipa/pr50605.C
new file mode 100644
index 00000000000..4910a37f8f2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr50605.C
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-early-inlining" } */
+
+class A
+{
+public:
+ int a;
+ void *stuff;
+};
+
+class B
+{
+public:
+ int b;
+ void *other_stuff;
+ A array[50];
+};
+
+extern B gb;
+
+int process_A (A *a)
+{
+ return a->a;
+}
+
+int process_A_complex (A *a)
+{
+ return process_A (a+3);
+}
+
+int process_B (B *b)
+{
+ return process_A_complex (&b->array[0]);
+}
+
+int foo (void)
+{
+ return process_B (&gb);
+}
+
diff --git a/gcc/testsuite/g++.dg/lookup/name-clash9.C b/gcc/testsuite/g++.dg/lookup/name-clash9.C
index 4167f47b4a9..1e04fafd5b9 100644
--- a/gcc/testsuite/g++.dg/lookup/name-clash9.C
+++ b/gcc/testsuite/g++.dg/lookup/name-clash9.C
@@ -3,6 +3,6 @@
struct A
{
- struct type {}; // { dg-error "conflicts with previous" }
- typedef int type; // { dg-error "declaration" }
+ struct type {}; // { dg-message "previous" }
+ typedef int type; // { dg-error "conflicts" }
};
diff --git a/gcc/testsuite/g++.dg/lookup/pr6936.C b/gcc/testsuite/g++.dg/lookup/pr6936.C
new file mode 100644
index 00000000000..377fbcce1e3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/pr6936.C
@@ -0,0 +1,23 @@
+// { dg-do compile }
+// PR c++/6936
+
+struct Baser
+{
+ enum { j, i }; // { dg-error "inaccessible" }
+};
+
+struct Base : Baser
+{
+ static void j();
+ static void i();
+};
+
+struct Derv : Base
+{
+ using Baser::j;
+private:
+ using Baser::i;
+};
+
+int k = Derv::j;
+int l = Derv::i; // { dg-error "context" }
diff --git a/gcc/testsuite/g++.dg/lookup/struct1.C b/gcc/testsuite/g++.dg/lookup/struct1.C
index f4b83ecf6b8..7c1e38c1863 100644
--- a/gcc/testsuite/g++.dg/lookup/struct1.C
+++ b/gcc/testsuite/g++.dg/lookup/struct1.C
@@ -2,10 +2,10 @@
// the definition of C.
struct A;
-typedef struct A B; // { dg-error "previous declaration" }
+typedef struct A B; // { dg-message "previous declaration" }
struct B; // { dg-error "using typedef-name" }
-typedef struct { int i; } C; // { dg-error "previous declaration" }
+typedef struct { int i; } C; // { dg-message "previous declaration" }
struct C; // { dg-error "using typedef-name" }
struct D;
diff --git a/gcc/testsuite/g++.dg/lookup/using24.C b/gcc/testsuite/g++.dg/lookup/using24.C
new file mode 100644
index 00000000000..4413be1f032
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using24.C
@@ -0,0 +1,12 @@
+// PR c++/26256
+// { dg-do compile }
+
+struct A { int next; };
+struct B { int next; };
+struct C : B { using B::next; };
+
+struct D : A, C
+{
+ using C::next;
+ void f() { next = 1; }
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using25.C b/gcc/testsuite/g++.dg/lookup/using25.C
new file mode 100644
index 00000000000..eb605700d8d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using25.C
@@ -0,0 +1,28 @@
+// PR c++/26256
+// { dg-do run }
+
+struct A
+{
+ int next;
+};
+
+struct B
+{
+ int next;
+};
+
+struct C : public A, public B
+{
+ using A::next;
+};
+
+void foo(C& c) { c.next = 42; }
+
+int main()
+{
+ C c;
+ foo (c);
+ c.B::next = 12;
+ if (c.next != 42 || c.A::next != 42 || c.B::next != 12)
+ __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using26.C b/gcc/testsuite/g++.dg/lookup/using26.C
new file mode 100644
index 00000000000..141d14581c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using26.C
@@ -0,0 +1,27 @@
+// PR c++/26256
+// { dg-do compile }
+
+struct A
+{
+ double next;
+};
+
+struct B
+{
+private:
+ int next; // { dg-error "private" }
+};
+
+struct C
+{
+ int next;
+};
+
+struct D : A, B, C // { dg-error "context" }
+{
+ using B::next;
+ void f()
+ {
+ next = 12;
+ }
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using27.C b/gcc/testsuite/g++.dg/lookup/using27.C
new file mode 100644
index 00000000000..c94cf6ea1a5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using27.C
@@ -0,0 +1,48 @@
+// PR c++/26256
+// { dg-do run }
+
+struct A
+{
+ typedef int type;
+};
+
+struct B
+{
+ typedef double type;
+};
+
+struct C : A, B
+{
+ using A::type;
+ type d;
+
+ void f()
+ {
+ type e;
+ if (sizeof (type) != sizeof (A::type))
+ __builtin_abort();
+ }
+
+ void g();
+};
+
+void C::g()
+{
+ type x;
+ if (sizeof (type) != sizeof (A::type))
+ __builtin_abort();
+}
+
+int main ()
+{
+ if (sizeof (C::type) != sizeof (A::type))
+ __builtin_abort();
+
+ if (sizeof (C::d) != sizeof (A::type))
+ __builtin_abort();
+
+ C::type x;
+ C c;
+ c.f();
+ c.g();
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using28.C b/gcc/testsuite/g++.dg/lookup/using28.C
new file mode 100644
index 00000000000..ae4067a23ea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using28.C
@@ -0,0 +1,11 @@
+// PR c++/26256
+// { dg-do compile }
+
+struct A { int f; };
+struct B { int f; };
+struct C : A, B { using B::f; };
+
+struct D : C
+{
+ void g() { f = 1; }
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using29.C b/gcc/testsuite/g++.dg/lookup/using29.C
new file mode 100644
index 00000000000..428021cf778
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using29.C
@@ -0,0 +1,81 @@
+// { dg-do compile }
+
+struct A
+{
+ int i;
+};
+
+struct B
+{
+ int i;
+};
+
+struct C : A, B
+{
+ using A::i; // { dg-message "previous" }
+ using B::i; // { dg-error "redeclaration" }
+};
+
+struct E
+{
+ typedef int type;
+};
+
+struct F
+{
+ typedef int type;
+};
+
+struct G : E, F
+{
+ using E::type; // { dg-message "previous" }
+ using F::type; // { dg-error "redeclaration" }
+};
+
+struct H
+{
+ typedef int type;
+};
+
+struct I : H
+{
+ typedef int type; // { dg-message "previous" }
+ using H::type; // { dg-error "conflicts" }
+};
+
+struct I2 : H
+{
+ using H::type; // { dg-message "previous" }
+ typedef int type; // { dg-error "conflicts" }
+};
+
+struct J
+{
+ struct type {};
+};
+
+struct K : J
+{
+ struct type {}; // { dg-message "previous" }
+ using J::type; // { dg-error "conflicts" }
+};
+
+struct L : J
+{
+ using J::type; // { dg-message "previous" }
+ struct type {}; // { dg-error "conflicts" }
+};
+
+struct M
+{
+ typedef int type;
+ struct type2 {};
+};
+
+struct N : M
+{
+ using M::type; // { dg-message "previous" }
+ using M::type; // { dg-error "redeclaration" }
+ using M::type2; // { dg-message "previous" }
+ using M::type2; // { dg-error "redeclaration" }
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using30.C b/gcc/testsuite/g++.dg/lookup/using30.C
new file mode 100644
index 00000000000..3fbe96c3ce8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using30.C
@@ -0,0 +1,8 @@
+// { dg-do compile }
+
+struct H { typedef int type; };
+struct J : H
+{
+ struct type {}; // { dg-message "previous" }
+ using H::type; // { dg-error "conflicts" }
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using31.C b/gcc/testsuite/g++.dg/lookup/using31.C
new file mode 100644
index 00000000000..3b1f6e90e10
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using31.C
@@ -0,0 +1,8 @@
+// { dg-do compile }
+
+struct H2 { int f (); };
+struct J2 : H2
+{
+ struct f {};
+ using H2::f;
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using32.C b/gcc/testsuite/g++.dg/lookup/using32.C
new file mode 100644
index 00000000000..cc0e96ca6b1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using32.C
@@ -0,0 +1,9 @@
+// { dg-do compile }
+
+struct T { struct type {}; };
+struct T2 : T { using T::type; };
+struct T3 : T2
+{
+ struct type {};
+ type t;
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using33.C b/gcc/testsuite/g++.dg/lookup/using33.C
new file mode 100644
index 00000000000..a80be036442
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using33.C
@@ -0,0 +1,26 @@
+// { dg-do run }
+
+template <class T>
+struct Foo
+{
+ int k (float) {return 0;}
+};
+
+template <class T>
+struct Baz
+{
+ int k (int) {return 1;}
+};
+
+template <class T>
+struct Bar : Foo<T> , Baz<T>
+{
+ using Foo<T>::k;
+ using Baz<T>::k;
+};
+
+int main()
+{
+ Bar<int> bar;
+ return bar.k( 1.0f );
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using34.C b/gcc/testsuite/g++.dg/lookup/using34.C
new file mode 100644
index 00000000000..79c019d0216
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using34.C
@@ -0,0 +1,10 @@
+// { dg-do compile }
+
+struct A { int f (); };
+struct B : A
+{
+ using A::f;
+ struct f {};
+ void g() { f(); struct f ff; }
+ struct f ff;
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using35.C b/gcc/testsuite/g++.dg/lookup/using35.C
new file mode 100644
index 00000000000..e7e82741d64
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using35.C
@@ -0,0 +1,11 @@
+// { dg-do compile }
+
+struct A { typedef int type; };
+struct B { typedef int type; };
+struct C : B { using B::type; };
+
+struct D : A, C
+{
+ using C::type;
+ void f() { type t = 0;}
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using36.C b/gcc/testsuite/g++.dg/lookup/using36.C
new file mode 100644
index 00000000000..966c60b8961
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using36.C
@@ -0,0 +1,31 @@
+// PR c++/25994
+// { dg-do run }
+
+struct B1
+{
+ void f (char) {}
+ void f (double) { __builtin_abort(); }
+};
+
+struct B2
+{
+ void f (double) { __builtin_abort(); }
+ void f (int) {}
+};
+
+struct D : public B1, public B2
+{
+ using B1::f;
+ using B2::f;
+ void g ()
+ {
+ f ('a'); // should call B1::f(char)
+ f (33); // should call B2::f(int)
+ }
+};
+
+int main()
+{
+ D d;
+ d.g();
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using37.C b/gcc/testsuite/g++.dg/lookup/using37.C
new file mode 100644
index 00000000000..a71206e89f7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using37.C
@@ -0,0 +1,22 @@
+// PR c++/30195
+// { dg-do run }
+
+template<class T> struct B
+{
+ void foo(T) {}
+};
+
+template<class T>
+struct D : B<int>, B<double>
+{
+ using B<int>::foo;
+ using B<double>::foo;
+ void bar() { foo(3); }
+};
+
+int main()
+{
+ D<int> x;
+ x.bar();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using38.C b/gcc/testsuite/g++.dg/lookup/using38.C
new file mode 100644
index 00000000000..377fbcce1e3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using38.C
@@ -0,0 +1,23 @@
+// { dg-do compile }
+// PR c++/6936
+
+struct Baser
+{
+ enum { j, i }; // { dg-error "inaccessible" }
+};
+
+struct Base : Baser
+{
+ static void j();
+ static void i();
+};
+
+struct Derv : Base
+{
+ using Baser::j;
+private:
+ using Baser::i;
+};
+
+int k = Derv::j;
+int l = Derv::i; // { dg-error "context" }
diff --git a/gcc/testsuite/g++.dg/lookup/using39.C b/gcc/testsuite/g++.dg/lookup/using39.C
new file mode 100644
index 00000000000..56ae89a4a22
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using39.C
@@ -0,0 +1,63 @@
+// { dg-do run }
+
+template <class T>
+struct A
+{
+ int f() { return 1; }
+};
+
+template <class T>
+struct B : A<T>
+{
+ int f() { return 2; }
+
+ using A<T>::f;
+ void g()
+ {
+ if (A<T>::f() != 1 )
+ __builtin_abort();
+
+ if( B<T>::f() != 2 )
+ __builtin_abort();
+
+ if( this->f() != 2 )
+ __builtin_abort();
+ }
+};
+
+template <class T>
+struct C
+{
+ int h( int i ) { return 1; }
+ int h( double d ) { return 2; }
+};
+
+template <class T>
+struct D : private C<T>
+{
+ using C<T>::h;
+ int h( char c ) { return 0; }
+ int h() { return 3; }
+};
+
+int main()
+{
+ B<int> b;
+ b.g();
+ b.f();
+ b.A<int>::f();
+ b.B<int>::f();
+
+ D<int> d;
+ if( d.h( 'a' ) != 0 )
+ __builtin_abort();
+
+ if( d.h( 3 ) != 1 )
+ __builtin_abort();
+
+ if( d.h( 3.14 ) != 2 )
+ __builtin_abort();
+
+ if( d.h() != 3 )
+ __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using40.C b/gcc/testsuite/g++.dg/lookup/using40.C
new file mode 100644
index 00000000000..1bcdd0dbf5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using40.C
@@ -0,0 +1,28 @@
+// { dg-do compile }
+
+struct Base
+{
+ void f();
+ typedef int type;
+ struct Type {};
+ int i;
+ static int j;
+};
+
+struct A : Base
+{
+ using Base::f; // { dg-message "previous declaration" }
+ using Base::f; // { dg-error "redeclaration" }
+
+ using Base::type; // { dg-message "previous declaration" }
+ using Base::type; // { dg-error "redeclaration" }
+
+ using Base::Type; // { dg-message "previous declaration" }
+ using Base::Type; // { dg-error "redeclaration" }
+
+ using Base::i; // { dg-message "previous declaration" }
+ using Base::i; // { dg-error "redeclaration" }
+
+ using Base::j; // { dg-message "previous declaration" }
+ using Base::j; // { dg-error "redeclaration" }
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using41.C b/gcc/testsuite/g++.dg/lookup/using41.C
new file mode 100644
index 00000000000..dcc618ba568
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using41.C
@@ -0,0 +1,21 @@
+// { dg-do compile }
+
+template <class T>
+struct Base
+{
+ void f();
+};
+
+template <class T>
+struct A : Base<T>
+{
+ using Base<T>::f; // { dg-message "previous declaration" }
+ using Base<T>::f; // { dg-error "redeclaration" }
+};
+
+template <class T, class U>
+struct B : Base<T>, Base<U>
+{
+ using Base<T>::f;
+ using Base<U>::f;
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using42.C b/gcc/testsuite/g++.dg/lookup/using42.C
new file mode 100644
index 00000000000..bca65acc74f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using42.C
@@ -0,0 +1,26 @@
+// PR c++/30195
+// { dg-do run }
+
+template <class T>
+struct B
+{
+ void foo(T) {}
+};
+
+template<class T>
+struct Out
+{
+ struct D : B<T>, B<double>
+ {
+ using B<T>::foo;
+ using B<double>::foo;
+ void bar() { foo(3); }
+ };
+};
+
+int main()
+{
+ Out<int>::D x;
+ x.bar();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using44.C b/gcc/testsuite/g++.dg/lookup/using44.C
new file mode 100644
index 00000000000..d754befd0a4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using44.C
@@ -0,0 +1,28 @@
+// PR c++/30195
+// { dg-do run }
+
+template <class T>
+struct B
+{
+ void foo(char) { __builtin_abort(); }
+ void foo(short) { __builtin_abort(); }
+ void foo(T) {}
+};
+
+template<class T>
+struct Out
+{
+ struct D : B<T>, B<double>
+ {
+ using B<T>::foo;
+ using B<double>::foo;
+ void bar() { foo(3); }
+ };
+};
+
+int main()
+{
+ Out<int>::D x;
+ x.bar();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using45.C b/gcc/testsuite/g++.dg/lookup/using45.C
new file mode 100644
index 00000000000..c92b794d9c5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using45.C
@@ -0,0 +1,33 @@
+// PR c++/30195
+// { dg-do run }
+
+template <class T>
+struct A
+{
+ int f(int) { return 0; }
+ int f(double) { return 1; }
+ int f(char) { return 2; }
+};
+
+template <class T>
+struct B : A<T>
+{
+ using A<T>::f;
+ int f(int) { return 3; }
+};
+
+int main()
+{
+ B<int> b;
+ if( b.f( 42 ) != 3 )
+ __builtin_abort();
+
+ if( b.f( 3.14 ) != 1 )
+ __builtin_abort();
+
+ if( b.f( 'a' ) != 2 )
+ __builtin_abort();
+
+ if( b.A<int>::f( 42 ) != 0 )
+ __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using46.C b/gcc/testsuite/g++.dg/lookup/using46.C
new file mode 100644
index 00000000000..6f0f5bca090
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using46.C
@@ -0,0 +1,62 @@
+// PR c++/51141
+// { dg-do compile }
+// { dg-options "-fpermissive -w -Werror" }
+
+typedef int size_t;
+template < size_t, size_t > struct AlignedBuffer {};
+
+template < typename > class VectorBufferBase
+{
+public:
+ allocateBuffer (size_t) {
+ }
+ buffer () {
+ }
+ *m_buffer;
+ size_t m_capacity;
+};
+
+template < typename T, size_t > class VectorBuffer:VectorBufferBase < T >
+{
+ typedef VectorBufferBase < T > Base;
+
+public:
+ VectorBuffer () {
+ }
+ allocateBuffer (size_t) {
+ m_capacity = 0;
+ }
+ Base::buffer;
+ Base::m_buffer;
+ Base::m_capacity;
+ size_t m_inlineBufferSize;
+
+ AlignedBuffer < 0, __alignof__ (T) > m_inlineBuffer;
+};
+
+template < typename T, size_t > class Vector
+{
+ typedef VectorBuffer < T,
+ 0 > Buffer;
+public:
+ void shrinkCapacity (size_t);
+
+ clear () {
+ shrinkCapacity (0);
+ }
+ Buffer m_buffer;
+};
+
+template < typename T, size_t inlineCapacity > void Vector < T,
+ inlineCapacity >::shrinkCapacity (size_t)
+{
+ m_buffer.allocateBuffer (0);
+}
+
+struct PatternDisjunction;
+struct YarrPattern {
+ reset () {
+ m_disjunctions.clear ();
+ }
+ Vector < PatternDisjunction *, 0 > m_disjunctions;
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using47.C b/gcc/testsuite/g++.dg/lookup/using47.C
new file mode 100644
index 00000000000..c81864705c4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using47.C
@@ -0,0 +1,29 @@
+// PR c++/51152
+// { dg-do compile }
+
+struct A
+{
+ int a;
+};
+
+struct B
+{
+ int b1;
+ int b2;
+ A b3;
+};
+
+struct C : B
+{
+ typedef int R;
+ typedef int S;
+ typedef int T;
+ using B::b1;
+ using B::b2;
+ using B::b3;
+ void f()
+ {
+ b3.a;
+ b3.~A();
+ }
+};
diff --git a/gcc/testsuite/g++.dg/lookup/using48.C b/gcc/testsuite/g++.dg/lookup/using48.C
new file mode 100644
index 00000000000..e6dc3fab77c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using48.C
@@ -0,0 +1,23 @@
+// PR c++/51190
+// { dg-do compile }
+
+struct A
+{
+ int i;
+};
+
+template<typename> struct B
+{
+ A* p;
+};
+
+template<typename T> struct C : B<T>
+{
+ using B<T>::p;
+
+ C() { p->i; }
+
+ int i1, i2, i3, i4, i5;
+};
+
+C<A> c;
diff --git a/gcc/testsuite/g++.dg/lookup/using49.C b/gcc/testsuite/g++.dg/lookup/using49.C
new file mode 100644
index 00000000000..391476ac472
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using49.C
@@ -0,0 +1,20 @@
+// PR c++/51188
+// { dg-do compile }
+
+#include <utility>
+class XBase {
+public:
+ virtual ~XBase() = 0;
+ enum ImpMode { Imp1, Imp2, Imp3 };
+};
+class X : public XBase {
+ class XBlock {};
+ using XBase::ImpMode;
+ using XBase::Imp3;
+ using XBase::Imp1;
+ using XBase::Imp2;
+ int _XBlocked;
+ std::pair<int,int> getImp(void) const {
+ return (std::make_pair(0, static_cast<int>(X::Imp1)));
+ }
+};
diff --git a/gcc/testsuite/g++.dg/other/pr49912.C b/gcc/testsuite/g++.dg/other/pr49912.C
new file mode 100644
index 00000000000..b8c3e5bedff
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/pr49912.C
@@ -0,0 +1,38 @@
+// PR rtl-optimization/49912
+// { dg-do compile }
+// { dg-require-effective-target freorder }
+// { dg-options "-O -freorder-blocks-and-partition" }
+
+int foo (int *);
+
+struct S
+{
+ int *m1 ();
+ S (int);
+ ~S () { foo (m1 ()); }
+};
+
+template <int>
+struct V
+{
+ S *v1;
+ void m2 (const S &);
+ S *base ();
+};
+
+template <int N>
+void V<N>::m2 (const S &x)
+{
+ S a = x;
+ S *l = base ();
+ while (l)
+ *v1 = *--l;
+}
+
+V<0> v;
+
+void
+foo ()
+{
+ v.m2 (0);
+}
diff --git a/gcc/testsuite/g++.dg/parse/ctor5.C b/gcc/testsuite/g++.dg/parse/ctor5.C
index 3ea23549c0b..f980b4a184f 100644
--- a/gcc/testsuite/g++.dg/parse/ctor5.C
+++ b/gcc/testsuite/g++.dg/parse/ctor5.C
@@ -2,7 +2,7 @@
struct A
{
- int i; // { dg-error "conflicts" }
+ int i; // { dg-message "previous" }
A() i() {} // { dg-error "declaration" }
};
diff --git a/gcc/testsuite/g++.dg/parse/elab1.C b/gcc/testsuite/g++.dg/parse/elab1.C
index 92fcd1ca69c..8108e1d0f6d 100644
--- a/gcc/testsuite/g++.dg/parse/elab1.C
+++ b/gcc/testsuite/g++.dg/parse/elab1.C
@@ -1,6 +1,6 @@
namespace Name {
- typedef void *(*Function)( void *, int ); // { dg-error "previous declaration" }
+ typedef void *(*Function)( void *, int ); // { dg-message "previous declaration" }
struct Foo {
struct Function xyz[5]; // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/parse/elab2.C b/gcc/testsuite/g++.dg/parse/elab2.C
index 6b42aed67a4..bf59f1b711d 100644
--- a/gcc/testsuite/g++.dg/parse/elab2.C
+++ b/gcc/testsuite/g++.dg/parse/elab2.C
@@ -2,6 +2,6 @@ struct A {};
struct B
{
- typedef A T; // { dg-error "previous declaration" }
+ typedef A T; // { dg-message "previous declaration" }
friend struct T; // { dg-error "" }
};
diff --git a/gcc/testsuite/g++.dg/parse/int-as-enum1.C b/gcc/testsuite/g++.dg/parse/int-as-enum1.C
index 7c37eb08792..c5ed261f625 100644
--- a/gcc/testsuite/g++.dg/parse/int-as-enum1.C
+++ b/gcc/testsuite/g++.dg/parse/int-as-enum1.C
@@ -2,5 +2,5 @@
// Origin: <wanderer@rsu.ru>
// { dg-do compile }
-typedef int A; // { dg-error "previous" }
+typedef int A; // { dg-message "previous" }
enum ::A {}; // { dg-error "typedef-name|expected unqualified-id" }
diff --git a/gcc/testsuite/g++.dg/parse/typedef1.C b/gcc/testsuite/g++.dg/parse/typedef1.C
index c4fbb950cf1..4d6f5b4fba5 100644
--- a/gcc/testsuite/g++.dg/parse/typedef1.C
+++ b/gcc/testsuite/g++.dg/parse/typedef1.C
@@ -1,3 +1,3 @@
// PR c++/6477
-typedef struct A_ *A; // { dg-error "previous declaration" }
+typedef struct A_ *A; // { dg-message "previous declaration" }
typedef struct A B; // { dg-error "typedef|invalid type" }
diff --git a/gcc/testsuite/g++.dg/parse/typedef3.C b/gcc/testsuite/g++.dg/parse/typedef3.C
index 6b4e531b677..3f6a7cb91b4 100644
--- a/gcc/testsuite/g++.dg/parse/typedef3.C
+++ b/gcc/testsuite/g++.dg/parse/typedef3.C
@@ -2,6 +2,6 @@
// Origin: Travis J.I. Corcoran <tjic@permabit.com>
// { dg-do compile }
-struct A { typedef A* Ptr; }; // { dg-error "previous declaration" }
+struct A { typedef A* Ptr; }; // { dg-message "previous declaration" }
struct A::Ptr; // { dg-error "typedef|not declare anything" }
diff --git a/gcc/testsuite/g++.dg/parse/typedef4.C b/gcc/testsuite/g++.dg/parse/typedef4.C
index 8599fd1d884..d4cec7f9c52 100644
--- a/gcc/testsuite/g++.dg/parse/typedef4.C
+++ b/gcc/testsuite/g++.dg/parse/typedef4.C
@@ -7,6 +7,6 @@
template<class T> class smart_ptr2 {
T* real_ptr;
public:
- typedef typename T::subT td; // { dg-error "previous declaration" }
+ typedef typename T::subT td; // { dg-message "previous declaration" }
friend class td; // { dg-error "typedef|not name a class" }
};
diff --git a/gcc/testsuite/g++.dg/parse/typedef5.C b/gcc/testsuite/g++.dg/parse/typedef5.C
index 7079f371333..ecd1d513efa 100644
--- a/gcc/testsuite/g++.dg/parse/typedef5.C
+++ b/gcc/testsuite/g++.dg/parse/typedef5.C
@@ -1,6 +1,6 @@
namespace A
{
- typedef int T; // { dg-error "previous declaration" }
+ typedef int T; // { dg-message "previous declaration" }
}
class A::T x; // { dg-error "using typedef-name|invalid type" }
diff --git a/gcc/testsuite/g++.dg/template/crash26.C b/gcc/testsuite/g++.dg/template/crash26.C
index f1bc399a31d..3be7ff97c26 100644
--- a/gcc/testsuite/g++.dg/template/crash26.C
+++ b/gcc/testsuite/g++.dg/template/crash26.C
@@ -4,5 +4,5 @@
// PR c++/18471: ICE redeclaration of typedef as class template
-typedef int X; // { dg-error "previous" }
+typedef int X; // { dg-message "previous" }
template<X> struct X {}; // { dg-error "typedef-name" }
diff --git a/gcc/testsuite/g++.dg/template/error46.C b/gcc/testsuite/g++.dg/template/error46.C
new file mode 100644
index 00000000000..0f4bdafb8a4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/error46.C
@@ -0,0 +1,11 @@
+// PR c++/51230
+
+template<int> struct A {};
+
+template<int N> void foo(A<N>, A<N>); // { dg-message "template" }
+
+void bar()
+{
+ foo(A<0>(), A<1>()); // { dg-error "no matching" }
+}
+// { dg-message "candidate|parameter 'N' ('0' and '1')" { target *-*-* } 9 }
diff --git a/gcc/testsuite/g++.dg/template/nontype4.C b/gcc/testsuite/g++.dg/template/nontype4.C
index ab39ed44397..41e3e22c000 100644
--- a/gcc/testsuite/g++.dg/template/nontype4.C
+++ b/gcc/testsuite/g++.dg/template/nontype4.C
@@ -7,7 +7,7 @@
template <int> struct A
{
- typedef A<0> B; // { dg-error "previous declaration" }
+ typedef A<0> B; // { dg-message "previous declaration" }
template <B> struct B {}; // { dg-error "not a valid type|typedef" }
};
diff --git a/gcc/testsuite/g++.dg/template/static4.C b/gcc/testsuite/g++.dg/template/static4.C
index c5486326cdd..526ced67e51 100644
--- a/gcc/testsuite/g++.dg/template/static4.C
+++ b/gcc/testsuite/g++.dg/template/static4.C
@@ -1,6 +1,6 @@
template <class R>
struct A {
- static int _test; // { dg-error "" }
+ static int _test; // { dg-message "" }
static int _test; // { dg-error "" }
};
template <class R> int A<R>::_test = 0;
diff --git a/gcc/testsuite/g++.dg/template/typedef1.C b/gcc/testsuite/g++.dg/template/typedef1.C
index 75b00e0fb2a..270adcdc984 100644
--- a/gcc/testsuite/g++.dg/template/typedef1.C
+++ b/gcc/testsuite/g++.dg/template/typedef1.C
@@ -12,7 +12,7 @@ template <typename T> struct A
template <typename T> struct B
{
- typedef int xxx; // { dg-error "" }
+ typedef int xxx; // { dg-message "" }
typedef T xxx; // { dg-error "" }
typedef typename A<T>::type xxx; // { dg-error "" }
typedef A<int>::type xxx; // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/template/unify11.C b/gcc/testsuite/g++.dg/template/unify11.C
index 25606dc4af8..85bdbbc940a 100644
--- a/gcc/testsuite/g++.dg/template/unify11.C
+++ b/gcc/testsuite/g++.dg/template/unify11.C
@@ -6,9 +6,10 @@ struct A
{
};
-template <typename S, typename T, typename U, typename S::v = &S::v::s>
+template <typename S, typename T, typename U,
+ typename S::v = &S::v::s> // { dg-error "is not a" }
typename S::A
-foo (S c, T t, U u) // { dg-message "note" }
+foo (S c, T t, U u)
{
}
@@ -20,8 +21,7 @@ struct B
C (U t)
{
A a;
- A b = foo (this, a, t); // { dg-error "(no matching function|is not a)" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 23 }
+ A b = foo (this, a, t); // { dg-error "no matching function" }
}
} c;
B () : c (A ())
diff --git a/gcc/testsuite/g++.dg/template/using2.C b/gcc/testsuite/g++.dg/template/using2.C
index 6dd9ef46ce7..5987254d432 100644
--- a/gcc/testsuite/g++.dg/template/using2.C
+++ b/gcc/testsuite/g++.dg/template/using2.C
@@ -7,24 +7,25 @@
template <class T>
struct Foo {
- int i; // { dg-error "Foo" }
+ int i;
};
struct Baz
{
- int i; // { dg-error "Baz" }
+ int i;
};
template <class T>
-struct Bar : public Foo<T>, Baz {
- using Foo<T>::i;
- using Baz::i;
+struct Bar : public Foo<T>, Baz
+{
+ using Foo<T>::i; // { dg-message "previous declaration" }
+ using Baz::i; // { dg-error "redeclaration" }
- int foo () { return i; } // { dg-error "request for member" }
+ int foo () { return i; }
};
void foo (Bar<int> &bar)
{
- bar.foo(); // { dg-message "required" }
+ bar.foo();
}
diff --git a/gcc/testsuite/g++.dg/template/virtual2.C b/gcc/testsuite/g++.dg/template/virtual2.C
new file mode 100644
index 00000000000..83b7ed6beae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/virtual2.C
@@ -0,0 +1,11 @@
+// PR c++/51137
+
+struct A {};
+
+template<int> struct B : virtual A
+{
+ void foo()
+ {
+ (new A(*this))->A::~A();
+ }
+};
diff --git a/gcc/testsuite/g++.dg/tm/pr47747.C b/gcc/testsuite/g++.dg/tm/pr47747.C
new file mode 100644
index 00000000000..3b50904b5d9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tm/pr47747.C
@@ -0,0 +1,21 @@
+// { dg-do compile }
+// { dg-options "-fgnu-tm -O" }
+
+class InputStream
+{
+ public:
+// __attribute__((transaction_safe))
+ virtual unsigned int readUint32 () = 0;
+};
+
+class Building
+{
+ public:
+ __attribute__((transaction_safe))
+ Building (InputStream *stream);
+};
+
+Building::Building (InputStream *stream)
+{
+ stream->readUint32 (); /* { dg-error "InputStream::readUint32" } */
+}
diff --git a/gcc/testsuite/g++.dg/tm/template-1.C b/gcc/testsuite/g++.dg/tm/template-1.C
index b93828a1dc3..cb6bb382fe3 100644
--- a/gcc/testsuite/g++.dg/tm/template-1.C
+++ b/gcc/testsuite/g++.dg/tm/template-1.C
@@ -30,6 +30,7 @@ int f1()
return foo<TrueFalse>() + bar<TrueFalse>();
}
-/* 4 transactions overall, two of the write to global: */
+/* 4 transactions overall, two of them write to global: */
/* { dg-final { scan-tree-dump-times "ITM_RU4\\s*\\(&global" 4 "tmmark" } } */
/* { dg-final { scan-tree-dump-times "ITM_WU4\\s*\\(&global" 2 "tmmark" } } */
+/* { dg-final { cleanup-tree-dump "tmmark" } } */
diff --git a/gcc/testsuite/g++.dg/tm/template-2.C b/gcc/testsuite/g++.dg/tm/template-2.C
new file mode 100644
index 00000000000..53870246a58
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tm/template-2.C
@@ -0,0 +1,22 @@
+// { dg-do compile }
+// { dg-options "-fgnu-tm -O -std=c++0x -fdump-tree-tmmark" }
+
+struct TrueFalse
+{
+};
+
+int global;
+
+template<typename T> int foo()
+{
+ return __transaction_atomic (global + 2)
+ + __transaction_atomic (global + 3);
+}
+
+int f1()
+{
+ return foo<TrueFalse>();
+}
+
+/* { dg-final { scan-tree-dump-times "ITM_RU" 2 "tmmark" } } */
+/* { dg-final { cleanup-tree-dump "tmmark" } } */
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr50741.C b/gcc/testsuite/g++.dg/tree-ssa/pr50741.C
new file mode 100644
index 00000000000..843a7be4a7b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr50741.C
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -g" } */
+/* PR middle-end/50741 */
+
+struct PublishLo
+{
+ const char *functionName;
+ ~PublishLo();
+};
+struct A { A(); };
+A::A()
+{
+ static PublishLo _rL_53 = {__FUNCTION__};
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wzero-as-null-pointer-constant-3.C b/gcc/testsuite/g++.dg/warn/Wzero-as-null-pointer-constant-3.C
new file mode 100644
index 00000000000..ed54143a027
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wzero-as-null-pointer-constant-3.C
@@ -0,0 +1,22 @@
+// PR c++/51290
+// { dg-options "-Wzero-as-null-pointer-constant" }
+
+class A { int a; };
+
+class B { int b; };
+
+class C : public A, public B
+{
+ private:
+ static void foo (A *x)
+ {
+ C *y = static_cast<C *>(x);
+ (void) y;
+ }
+
+ static void bar (B *x)
+ {
+ C *y = static_cast<C *>(x);
+ (void) y;
+ }
+};
diff --git a/gcc/testsuite/g++.old-deja/g++.benjamin/typedef01.C b/gcc/testsuite/g++.old-deja/g++.benjamin/typedef01.C
index 79a965b16f2..d5ed39af364 100644
--- a/gcc/testsuite/g++.old-deja/g++.benjamin/typedef01.C
+++ b/gcc/testsuite/g++.old-deja/g++.benjamin/typedef01.C
@@ -18,7 +18,7 @@ typedef I I;
//p3--cannot redefine to a different type in a given scope
class complex2 { /* ... */ };// { dg-error "" } .*
typedef int complex2;// { dg-error "" } .*
-typedef int complex3;// { dg-error "" } .*
+typedef int complex3;// { dg-message "" } .*
class complex3 { /* ... */ };// { dg-error "" } .*
@@ -37,7 +37,7 @@ struct S {
~S();
};
-typedef struct S T; // { dg-error "previous declaration" }
+typedef struct S T; // { dg-message "previous declaration" }
S a = T(); // OK
struct T * p; // { dg-error "" } using typedef after struct
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/line1.C b/gcc/testsuite/g++.old-deja/g++.brendan/line1.C
index b14ed8efa18..94130ec4676 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/line1.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/line1.C
@@ -1,4 +1,4 @@
// { dg-do assemble }
// GROUPS passed error-messages
-typedef struct s S;// { dg-error "" } previous.*
+typedef struct s S;// { dg-message "" } previous.*
struct S { int member:1; }; // the lineno for this should be 2, not 0// { dg-error "" } conflicting types.*
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/misc14.C b/gcc/testsuite/g++.old-deja/g++.brendan/misc14.C
index d2e49095a3b..ea6ce4c74c7 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/misc14.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/misc14.C
@@ -3,11 +3,11 @@
class X {
public:
enum e {
- New // { dg-error "conflicts with previous" }
+ New // { dg-message "previous" }
, // { dg-error "comma at end" "" { target c++98 } }
};
- static int New(int); // { dg-error "declaration of" }
+ static int New(int); // { dg-error "conflicts with a previous" }
};
int main() {}
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900127_02.C b/gcc/testsuite/g++.old-deja/g++.bugs/900127_02.C
index 0ae23881fc4..12ae64a36a0 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900127_02.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900127_02.C
@@ -23,12 +23,12 @@ int global1 (); // { dg-error "" } xref for below
int global1; // { dg-error "" } caught
struct struct_0 {
- int class_local (); // { dg-error "" }
+ int class_local (); // { dg-message "" }
int class_local; // { dg-error "" }
};
struct struct_1 {
- int class_local; // { dg-error "" }
+ int class_local; // { dg-message "" }
int class_local (); // { dg-error "" }
};
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/scoping16.C b/gcc/testsuite/g++.old-deja/g++.jason/scoping16.C
index 9b9d915ba4e..1c225c75f78 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/scoping16.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/scoping16.C
@@ -1,5 +1,5 @@
// { dg-do assemble }
struct A {
- int a(); // { dg-error "" }
+ int a(); // { dg-message "" }
int a; // { dg-error "" }
};
diff --git a/gcc/testsuite/g++.old-deja/g++.other/anon7.C b/gcc/testsuite/g++.old-deja/g++.other/anon7.C
index ebc378005cd..6a951a97c62 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/anon7.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/anon7.C
@@ -2,13 +2,13 @@
struct A {
union {
- int a; // { dg-error "" } conflicts with previous declaration
+ int a; // { dg-message "" } conflicts with previous declaration
};
int a; // { dg-error "" }
};
struct B {
- int b; // { dg-error "" } conflicts with previous declaration
+ int b; // { dg-message "" } conflicts with previous declaration
union {
int b; // { dg-error "" } duplicate member
};
@@ -16,7 +16,7 @@ struct B {
struct C {
union {
- int c; // { dg-error "" } conflicts with previous declaration
+ int c; // { dg-message "" } conflicts with previous declaration
};
union {
int c; // { dg-error "" } duplicate member
diff --git a/gcc/testsuite/g++.old-deja/g++.other/elab1.C b/gcc/testsuite/g++.old-deja/g++.other/elab1.C
index 5588651dfe5..f09ff6f1c4c 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/elab1.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/elab1.C
@@ -1,5 +1,5 @@
// { dg-do assemble }
-typedef struct {} S; // { dg-error "" } Previous declaration of S
+typedef struct {} S; // { dg-message "" } Previous declaration of S
S s1;
struct S* s2; // { dg-error "" } S is a typedef name
diff --git a/gcc/testsuite/g++.old-deja/g++.other/redecl1.C b/gcc/testsuite/g++.old-deja/g++.other/redecl1.C
index bd6382ee052..d9797865875 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/redecl1.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/redecl1.C
@@ -1,6 +1,6 @@
// { dg-do assemble }
struct X{
void i();
- void i(int); // { dg-error "" }
+ void i(int); // { dg-message "" }
int i; // { dg-error "" } conflict
};
diff --git a/gcc/testsuite/g++.old-deja/g++.other/syntax4.C b/gcc/testsuite/g++.old-deja/g++.other/syntax4.C
index 7aed1f5b140..445c539c921 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/syntax4.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/syntax4.C
@@ -17,7 +17,7 @@ class X {
class Y {
public:
- typedef ::X W; // { dg-error "" } previous declaration
+ typedef ::X W; // { dg-message "" } previous declaration
class Z;
};
diff --git a/gcc/testsuite/g++.old-deja/g++.other/typedef7.C b/gcc/testsuite/g++.old-deja/g++.other/typedef7.C
index 42cf4f1c5e2..93784c08d87 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/typedef7.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/typedef7.C
@@ -8,13 +8,13 @@ typedef int I;
// invalid.
struct A {
- typedef int I; // { dg-error "" }
+ typedef int I; // { dg-message "" }
typedef int I; // { dg-error "" }
};
template <class T>
struct S {
- typedef int I; // { dg-error "" }
+ typedef int I; // { dg-message "" }
typedef int I; // { dg-error "" }
};
diff --git a/gcc/testsuite/g++.old-deja/g++.other/using1.C b/gcc/testsuite/g++.old-deja/g++.other/using1.C
index d734576ac8c..48c29f79b19 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/using1.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/using1.C
@@ -16,12 +16,12 @@ public:
using B::b;
};
-class D2 : public B { // { dg-error "" } conflicting access specifications
+class D2 : public B {
public:
using B::a;
- using B::b;
+ using B::b; // { dg-message "" } conflicting declaration
private:
- using B::b;
+ using B::b; // { dg-error "" } conflicts
};
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr44707.c b/gcc/testsuite/gcc.c-torture/compile/pr44707.c
index 9031f0042c9..d5d39fc83c8 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr44707.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr44707.c
@@ -9,6 +9,6 @@ foo (void)
int e3 = v.b;
int e4 = v.c;
int e5 = v.d;
- __asm__ volatile ("/* %0 %1 %2 %3 %4 */" : : "nro" (e1), "nro" (e2), "nro" (e3), "nro" (e4), "nro" (e5));
+ __asm__ volatile ("" : : "nro" (e1), "nro" (e2), "nro" (e3), "nro" (e4), "nro" (e5));
}
diff --git a/gcc/testsuite/gcc.dg/atomic-compare-exchange-4.c b/gcc/testsuite/gcc.dg/atomic-compare-exchange-4.c
index d89e72f8171..b6c783ddaba 100644
--- a/gcc/testsuite/gcc.dg/atomic-compare-exchange-4.c
+++ b/gcc/testsuite/gcc.dg/atomic-compare-exchange-4.c
@@ -1,8 +1,9 @@
/* Test __atomic routines for existence and proper execution on 8 byte
values with each valid memory model. */
/* { dg-do run } */
-/* { dg-require-effective-target sync_long_long } */
+/* { dg-require-effective-target sync_long_long_runtime } */
/* { dg-options "" } */
+/* { dg-options "-march=pentium" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
/* Test the execution of __atomic_compare_exchange_n builtin for a long_long. */
diff --git a/gcc/testsuite/gcc.dg/atomic-compare-exchange-5.c b/gcc/testsuite/gcc.dg/atomic-compare-exchange-5.c
index e716dcb350c..4cc0209b33f 100644
--- a/gcc/testsuite/gcc.dg/atomic-compare-exchange-5.c
+++ b/gcc/testsuite/gcc.dg/atomic-compare-exchange-5.c
@@ -1,8 +1,8 @@
/* Test __atomic routines for existence and proper execution on 16 byte
values with each valid memory model. */
/* { dg-do run } */
-/* { dg-require-effective-target sync_int_128 } */
-/* { dg-options "-mcx16" { target { x86_64-*-* } } } */
+/* { dg-require-effective-target sync_int_128_runtime } */
+/* { dg-options "-mcx16" { target { i?86-*-* x86_64-*-* } } } */
/* Test the execution of __atomic_compare_exchange_n builtin for an int_128. */
diff --git a/gcc/testsuite/gcc.dg/atomic-exchange-4.c b/gcc/testsuite/gcc.dg/atomic-exchange-4.c
index f0530fc462c..13022dd38d2 100644
--- a/gcc/testsuite/gcc.dg/atomic-exchange-4.c
+++ b/gcc/testsuite/gcc.dg/atomic-exchange-4.c
@@ -1,8 +1,9 @@
/* Test __atomic routines for existence and proper execution on 8 byte
values with each valid memory model. */
/* { dg-do run } */
-/* { dg-require-effective-target sync_long_long } */
+/* { dg-require-effective-target sync_long_long_runtime } */
/* { dg-options "" } */
+/* { dg-options "-march=pentium" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
/* Test the execution of the __atomic_X builtin for a long_long. */
diff --git a/gcc/testsuite/gcc.dg/atomic-exchange-5.c b/gcc/testsuite/gcc.dg/atomic-exchange-5.c
index 13fd6d1b8ec..b0c84b17fd3 100644
--- a/gcc/testsuite/gcc.dg/atomic-exchange-5.c
+++ b/gcc/testsuite/gcc.dg/atomic-exchange-5.c
@@ -1,8 +1,8 @@
/* Test __atomic routines for existence and proper execution on 16 byte
values with each valid memory model. */
/* { dg-do run } */
-/* { dg-require-effective-target sync_int_128 } */
-/* { dg-options "-mcx16" { target { x86_64-*-* } } } */
+/* { dg-require-effective-target sync_int_128_runtime } */
+/* { dg-options "-mcx16" { target { i?86-*-* x86_64-*-* } } } */
/* Test the execution of the __atomic_X builtin for a 16 byte value. */
diff --git a/gcc/testsuite/gcc.dg/atomic-generic-aux.c b/gcc/testsuite/gcc.dg/atomic-generic-aux.c
index a6b552a5dfd..2f4cb2a88f7 100644
--- a/gcc/testsuite/gcc.dg/atomic-generic-aux.c
+++ b/gcc/testsuite/gcc.dg/atomic-generic-aux.c
@@ -19,17 +19,30 @@ __atomic_exchange (size_t size, void *obj, void *val, void *ret, int model)
}
+/* Note that the external version of this routine has the boolean weak/strong
+ parameter removed. This is required by teh external library. */
bool
-__atomic_compare_exchange (size_t size, void *obj, void *expected,
+__atomic_compare_exchange (size_t size, void *obj, void *expected,
void *desired, int model1, int model2)
{
+ bool ret;
if (!memcmp (obj, expected, size))
{
memcpy (obj, desired, size);
- return true;
+ ret = true;
}
- memcpy (expected, obj, size);
- return false;
+ else
+ {
+ memcpy (expected, obj, size);
+ ret = false;
+ }
+
+ /* Make sure the parameters have been properly adjusted for the external
+ function call (no weak/strong parameter. */
+ if (model1 != __ATOMIC_SEQ_CST || model2 != __ATOMIC_ACQUIRE)
+ ret = !ret;
+
+ return ret;
}
diff --git a/gcc/testsuite/gcc.dg/atomic-generic.c b/gcc/testsuite/gcc.dg/atomic-generic.c
index 8a5528c3653..d77e97dbf8a 100644
--- a/gcc/testsuite/gcc.dg/atomic-generic.c
+++ b/gcc/testsuite/gcc.dg/atomic-generic.c
@@ -41,12 +41,12 @@ main ()
if (memcmp (&b, &ones, size))
abort ();
- if (!__atomic_compare_exchange (&a, &b, &zero, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED))
+ if (!__atomic_compare_exchange (&a, &b, &zero, false, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE))
abort();
if (memcmp (&a, &zero, size))
abort ();
- if (__atomic_compare_exchange (&a, &b, &ones, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED))
+ if (__atomic_compare_exchange (&a, &b, &ones, false, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE))
abort();
if (memcmp (&b, &zero, size))
abort ();
diff --git a/gcc/testsuite/gcc.dg/atomic-load-4.c b/gcc/testsuite/gcc.dg/atomic-load-4.c
index 5cb7659da70..032ad246fd0 100644
--- a/gcc/testsuite/gcc.dg/atomic-load-4.c
+++ b/gcc/testsuite/gcc.dg/atomic-load-4.c
@@ -1,8 +1,9 @@
/* Test __atomic routines for existence and proper execution on 8 byte
values with each valid memory model. */
/* { dg-do run } */
-/* { dg-require-effective-target sync_long_long } */
+/* { dg-require-effective-target sync_long_long_runtime } */
/* { dg-options "" } */
+/* { dg-options "-march=pentium" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
extern void abort(void);
diff --git a/gcc/testsuite/gcc.dg/atomic-load-5.c b/gcc/testsuite/gcc.dg/atomic-load-5.c
index 2991e4d6c7a..31d806633e1 100644
--- a/gcc/testsuite/gcc.dg/atomic-load-5.c
+++ b/gcc/testsuite/gcc.dg/atomic-load-5.c
@@ -1,8 +1,8 @@
/* Test __atomic routines for existence and proper execution on 16 byte
values with each valid memory model. */
/* { dg-do run } */
-/* { dg-require-effective-target sync_int_128 } */
-/* { dg-options "-mcx16" { target { x86_64-*-* } } } */
+/* { dg-require-effective-target sync_int_128_runtime } */
+/* { dg-options "-mcx16" { target { i?86-*-* x86_64-*-* } } } */
extern void abort(void);
diff --git a/gcc/testsuite/gcc.dg/atomic-noinline-aux.c b/gcc/testsuite/gcc.dg/atomic-noinline-aux.c
index b05460e469b..deab7ae1de3 100644
--- a/gcc/testsuite/gcc.dg/atomic-noinline-aux.c
+++ b/gcc/testsuite/gcc.dg/atomic-noinline-aux.c
@@ -30,9 +30,15 @@ __atomic_store_1 (char *p, char v, int i)
*p = 1;
}
-int __atomic_compare_exchange_2 (short *p, short *a, short b, int x, int y, int z)
+int __atomic_compare_exchange_2 (short *p, short *a, short b, int y, int z)
{
- *p = 1;
+ /* Fail if the memory models aren't correct as that will indicate the external
+ call has failed to remove the weak/strong parameter as required by the
+ library. */
+ if (y != __ATOMIC_SEQ_CST || z != __ATOMIC_ACQUIRE)
+ *p = 0;
+ else
+ *p = 1;
}
char __atomic_fetch_add_1 (char *p, char v, int i)
diff --git a/gcc/testsuite/gcc.dg/atomic-noinline.c b/gcc/testsuite/gcc.dg/atomic-noinline.c
index eb0866e549e..626254d8a9a 100644
--- a/gcc/testsuite/gcc.dg/atomic-noinline.c
+++ b/gcc/testsuite/gcc.dg/atomic-noinline.c
@@ -31,7 +31,7 @@ main ()
if (ac != 1)
abort ();
- __atomic_compare_exchange_n (&as, &bs, cs, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+ __atomic_compare_exchange_n (&as, &bs, cs, 0, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
if (as != 1)
abort ();
diff --git a/gcc/testsuite/gcc.dg/atomic-op-4.c b/gcc/testsuite/gcc.dg/atomic-op-4.c
index 39650213edf..7c4a819bfaa 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-4.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-4.c
@@ -1,8 +1,9 @@
/* Test __atomic routines for existence and proper execution on 8 byte
values with each valid memory model. */
/* { dg-do run } */
-/* { dg-require-effective-target sync_long_long } */
+/* { dg-require-effective-target sync_long_long_runtime } */
/* { dg-options "" } */
+/* { dg-options "-march=pentium" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
/* Test the execution of the __atomic_*OP builtin routines for long long. */
diff --git a/gcc/testsuite/gcc.dg/atomic-op-5.c b/gcc/testsuite/gcc.dg/atomic-op-5.c
index 2ca71adc8f1..e78d8150997 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-5.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-5.c
@@ -1,8 +1,8 @@
/* Test __atomic routines for existence and proper execution on 16 byte
values with each valid memory model. */
/* { dg-do run } */
-/* { dg-require-effective-target sync_int_128 } */
-/* { dg-options "-mcx16" { target { x86_64-*-* } } } */
+/* { dg-require-effective-target sync_int_128_runtime } */
+/* { dg-options "-mcx16" { target { i?86-*-* x86_64-*-* } } } */
/* Test the execution of the __atomic_*OP builtin routines for an int_128. */
diff --git a/gcc/testsuite/gcc.dg/atomic-pr51256.c b/gcc/testsuite/gcc.dg/atomic-pr51256.c
new file mode 100644
index 00000000000..2d39549c890
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic-pr51256.c
@@ -0,0 +1,47 @@
+/* Test generic __atomic routines for various errors. */
+/* { dg-do compile } */
+/* { dg-require-effective-target sync_int_long } */
+/* { dg-options "-ansi" } */
+
+void f1 (void* p)
+{
+ __atomic_compare_exchange(p, p, p, 0, 0, 0); /* { dg-error "must be a non-void pointer type" } */
+}
+
+void f2 (int n)
+{
+ int a[n], b[n];
+ __atomic_load (&a, &b, __ATOMIC_SEQ_CST); /* { dg-error "must be a pointer to a constant size" } */
+}
+
+struct s { };
+void f3 (void)
+{
+ struct s a,b;
+ __atomic_load (&a, &b, __ATOMIC_SEQ_CST); /* { dg-error "must be a pointer to a nonzero size" } */
+}
+
+void f4 (int a, int b, int c)
+{
+ __atomic_load (&a, &b, &c, __ATOMIC_SEQ_CST); /* { dg-error "incorrect number of arguments" } */
+}
+
+void f5 (int a, int b)
+{
+ __atomic_load (&a, b, __ATOMIC_SEQ_CST); /* { dg-error "must be a pointer type" } */
+}
+
+void f6 (int a, char b)
+{
+ __atomic_load (&a, &b, __ATOMIC_SEQ_CST); /* { dg-error "size mismatch in argument" } */
+}
+
+void f7 (int a, int b)
+{
+ __atomic_load (&a, &b, 45); /* { dg-warning "invalid memory model argument" } */
+}
+
+void f8 (int a, int b, float c)
+{
+ __atomic_load (&a, &b, c); /* { dg-error "non-integer memory model argument" } */
+}
diff --git a/gcc/testsuite/gcc.dg/atomic-store-4.c b/gcc/testsuite/gcc.dg/atomic-store-4.c
index f77e1831ad8..0863be99d01 100644
--- a/gcc/testsuite/gcc.dg/atomic-store-4.c
+++ b/gcc/testsuite/gcc.dg/atomic-store-4.c
@@ -1,8 +1,9 @@
/* Test __atomic routines for existence and proper execution on 8 byte
values with each valid memory model. */
/* { dg-do run } */
-/* { dg-require-effective-target sync_long_long } */
+/* { dg-require-effective-target sync_long_long_runtime } */
/* { dg-options "" } */
+/* { dg-options "-march=pentium" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
/* Test the execution of the __atomic_store_n builtin for a long long. */
diff --git a/gcc/testsuite/gcc.dg/atomic-store-5.c b/gcc/testsuite/gcc.dg/atomic-store-5.c
index f976a052c7c..763d29e240c 100644
--- a/gcc/testsuite/gcc.dg/atomic-store-5.c
+++ b/gcc/testsuite/gcc.dg/atomic-store-5.c
@@ -1,8 +1,8 @@
/* Test __atomic routines for existence and proper execution on 16 byte
values with each valid memory model. */
/* { dg-do run } */
-/* { dg-require-effective-target sync_int_128 } */
-/* { dg-options "-mcx16" { target { x86_64-*-* } } } */
+/* { dg-require-effective-target sync_int_128_runtime } */
+/* { dg-options "-mcx16" { target { i?86-*-* x86_64-*-* } } } */
/* Test the execution of the __atomic_store_n builtin for a 16 byte value. */
diff --git a/gcc/testsuite/gcc.dg/autopar/pr49960-1.c b/gcc/testsuite/gcc.dg/autopar/pr49960-1.c
new file mode 100644
index 00000000000..ac9d5678499
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/autopar/pr49960-1.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-parallelize-loops=4 -fdump-tree-parloops-details -fdump-tree-optimized" } */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+int main()
+{
+ unsigned int x, y, idx, H = 1024, W = 1024;
+
+ int * tmps = (int *)malloc(H*W*sizeof(int));
+
+ /* This loop gets parallelized even though output dependences exist
+ between writes to 'tmps' that prevent parallelization.
+ For example: tmps[1] = 1, ..., tmps[1] = 17. */
+
+ for(x = 1; x < H; x++)
+ {
+ for(y = 1; y < W; y++)
+ {
+ idx = x*W+y;
+ tmps[idx % 4096] = idx;
+ }
+ }
+
+ for(x = 1; x < 8; x++)
+ printf("tmps[%d]=%d\n", x, tmps[x]);
+
+ return 0;
+}
+/* Check that no loop gets parallelized. */
+
+/* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 0 "parloops" } } */
+/* { dg-final { scan-tree-dump-times "loopfn" 0 "optimized" } } */
+/* { dg-final { cleanup-tree-dump "parloops" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/autopar/pr49960.c b/gcc/testsuite/gcc.dg/autopar/pr49960.c
new file mode 100644
index 00000000000..1f3482f170d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/autopar/pr49960.c
@@ -0,0 +1,49 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-parallelize-loops=4 -fdump-tree-parloops-details -fdump-tree-optimized" } */
+
+#include <stdio.h>
+#define MB 100
+#define NA 450
+#define MA 400
+
+int T[MA][MB],A[MA][NA],B[MB][NA];
+void MRTRBR(int MA_1, int NA_1, int MB_1)
+{
+ int i,j, t,k;
+
+ /* The outer most loop is not parallel because for different k's there
+ is write-write dependency for T[i][j]. */
+
+ /* The two inner loops don't get parallelized due to low number of
+ iterations. */
+
+ for (k = 3; k < NA_1; k++)
+ for (i = 3; i < MA_1; i++)
+ for (j = 3; j < MB_1; j++)
+ {
+ t = T[i][j];
+ T[i][j] = t+2+A[i][k]*B[j][k];
+ }
+}
+void main ()
+{
+ int j,i;
+
+ for (i = 3; i < MA; i++)
+ for (j = 3; j < MB; j++)
+ T[i][j] = (i>j?i:j);
+
+ MRTRBR (MA,NA,MB);
+
+ for (i = MA-1; i < MA; i++)
+ for (j = MB-10; j < MB; j++)
+ printf ("i %d j %d T[i][j] = %d\n",i,j,T[i][j]);
+}
+
+
+/* Check that the outer most loop doesn't get parallelized (thus no loop gets parallelized) */
+
+/* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 0 "parloops" } } */
+/* { dg-final { scan-tree-dump-times "loopfn" 0 "optimized" } } */
+/* { dg-final { cleanup-tree-dump "parloops" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/cpp/assert4.c b/gcc/testsuite/gcc.dg/cpp/assert4.c
index a05ef130206..514195313b3 100644
--- a/gcc/testsuite/gcc.dg/cpp/assert4.c
+++ b/gcc/testsuite/gcc.dg/cpp/assert4.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2006, 2008 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2006, 2008, 2009, 2011 Free Software Foundation, Inc.
Test builtin preprocessor assertions.
By Kaveh Ghazi <ghazi@caip.rutgers.edu>. */
@@ -7,7 +7,7 @@
/* Check for #system assertions. */
-#if defined __gnu_linux__
+#if defined __linux__
# if !#system(linux) || !#system(unix) || !#system(posix)
# error
# endif
diff --git a/gcc/testsuite/gcc.dg/delay-slot-2.c b/gcc/testsuite/gcc.dg/delay-slot-2.c
new file mode 100644
index 00000000000..79faf81c798
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/delay-slot-2.c
@@ -0,0 +1,116 @@
+/* PR rtl-optimization/51187 */
+/* Reported by Jurij Smakov <jurij@wooyd.org> */
+
+/* { dg-do compile } */
+/* { dg-options "-g -O2" } */
+
+extern int printf (__const char *__restrict __format, ...);
+extern void print_c_condition (const char *);
+
+enum decision_type
+{
+ DT_num_insns,
+ DT_mode, DT_code, DT_veclen,
+ DT_elt_zero_int, DT_elt_one_int, DT_elt_zero_wide, DT_elt_zero_wide_safe,
+ DT_const_int,
+ DT_veclen_ge, DT_dup, DT_pred, DT_c_test,
+ DT_accept_op, DT_accept_insn
+};
+
+struct decision_test
+{
+ struct decision_test *next;
+ enum decision_type type;
+
+ union
+ {
+ int num_insns;
+
+ struct
+ {
+ const char *name;
+ } pred;
+
+ const char *c_test;
+ int veclen;
+ int dup;
+ long intval;
+ int opno;
+
+ struct {
+ int code_number;
+ int lineno;
+ int num_clobbers_to_add;
+ } insn;
+ } u;
+};
+
+enum routine_type {
+ RECOG, SPLIT, PEEPHOLE2
+};
+
+void
+write_cond (struct decision_test *p, int depth,
+ enum routine_type subroutine_type)
+{
+ switch (p->type)
+ {
+ case DT_num_insns:
+ printf ("peep2_current_count >= %d", p->u.num_insns);
+ break;
+
+ case DT_code:
+ printf ("GET_CODE (x%d) == ", depth);
+ break;
+
+ case DT_veclen:
+ printf ("XVECLEN (x%d, 0) == %d", depth, p->u.veclen);
+ break;
+
+ case DT_elt_zero_int:
+ printf ("XINT (x%d, 0) == %d", depth, (int) p->u.intval);
+ break;
+
+ case DT_elt_one_int:
+ printf ("XINT (x%d, 1) == %d", depth, (int) p->u.intval);
+ break;
+
+ case DT_elt_zero_wide:
+ case DT_elt_zero_wide_safe:
+ printf ("XWINT (x%d, 0) == ", depth);
+ print_host_wide_int (p->u.intval);
+ break;
+
+ case DT_const_int:
+ printf ("x%d == const_int_rtx[MAX_SAVED_CONST_INT + (%d)]",
+ depth, (int) p->u.intval);
+ break;
+
+ case DT_veclen_ge:
+ printf ("XVECLEN (x%d, 0) >= %d", depth, p->u.veclen);
+ break;
+
+ case DT_dup:
+ printf ("rtx_equal_p (x%d, operands[%d])", depth, p->u.dup);
+ break;
+
+ case DT_pred:
+ printf ("%s (x%d)", p->u.pred.name, depth);
+ break;
+
+ case DT_c_test:
+ print_c_condition (p->u.c_test);
+ break;
+
+ case DT_accept_insn:
+ ((void)(__builtin_expect(!(subroutine_type == RECOG), 0) ? __builtin_unreachable(), 0 : 0));
+ ((void)(__builtin_expect(!(p->u.insn.num_clobbers_to_add), 0) ? __builtin_unreachable(), 0 : 0));
+ printf ("pnum_clobbers != NULL");
+ break;
+
+ default:
+ __builtin_unreachable();
+ }
+}
+
+/* { dg-final { scan-assembler "printf" } } */
diff --git a/gcc/testsuite/gcc.dg/di-longlong64-sync-1.c b/gcc/testsuite/gcc.dg/di-longlong64-sync-1.c
index 82a4ea24617..f04cf62e03d 100644
--- a/gcc/testsuite/gcc.dg/di-longlong64-sync-1.c
+++ b/gcc/testsuite/gcc.dg/di-longlong64-sync-1.c
@@ -1,6 +1,8 @@
/* { dg-do run } */
-/* { dg-require-effective-target sync_longlong } */
+/* { dg-require-effective-target sync_long_long_runtime } */
/* { dg-options "-std=gnu99" } */
+/* { dg-additional-options "-march=pentium" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
+
/* { 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 } */
diff --git a/gcc/testsuite/gcc.dg/di-sync-multithread.c b/gcc/testsuite/gcc.dg/di-sync-multithread.c
index c99878ea129..307ebf8b314 100644
--- a/gcc/testsuite/gcc.dg/di-sync-multithread.c
+++ b/gcc/testsuite/gcc.dg/di-sync-multithread.c
@@ -1,8 +1,9 @@
/* { dg-do run } */
-/* { dg-require-effective-target sync_longlong } */
+/* { dg-require-effective-target sync_long_long_runtime } */
/* { dg-require-effective-target pthread_h } */
/* { dg-require-effective-target pthread } */
/* { dg-options "-pthread -std=gnu99" } */
+/* { dg-additional-options "-march=pentium" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
/* test of long long atomic ops performed in parallel in 3 pthreads
david.gilbert@linaro.org */
diff --git a/gcc/testsuite/gcc.dg/lto/trans-mem-1_0.c b/gcc/testsuite/gcc.dg/lto/trans-mem-1_0.c
new file mode 100644
index 00000000000..87060ccf7e7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/trans-mem-1_0.c
@@ -0,0 +1,12 @@
+/* { dg-lto-options {{-flto -fgnu-tm}} } */
+/* { dg-lto-do link } */
+
+int i;
+
+main()
+{
+ __transaction_atomic
+ {
+ i = 0;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/lto/trans-mem-1_1.c b/gcc/testsuite/gcc.dg/lto/trans-mem-1_1.c
new file mode 100644
index 00000000000..cb80f320baa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/trans-mem-1_1.c
@@ -0,0 +1,9 @@
+#define dummy(func) \
+ __attribute__((noinline,noclone,used)) void func() { asm (""); }
+
+dummy(_ITM_beginTransaction)
+dummy(_ITM_commitTransaction)
+dummy(_ITM_WU4)
+dummy(_ITM_WU8)
+dummy(_ITM_registerTMCloneTable)
+dummy(_ITM_deregisterTMCloneTable)
diff --git a/gcc/testsuite/gcc.dg/lto/trans-mem-2_0.c b/gcc/testsuite/gcc.dg/lto/trans-mem-2_0.c
new file mode 100644
index 00000000000..301a711a4f5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/trans-mem-2_0.c
@@ -0,0 +1,22 @@
+/* { dg-lto-options {{-flto -fgnu-tm}} } */
+/* { dg-lto-do link } */
+
+extern void foobar() __attribute__((transaction_callable));
+
+#define dummy(func) \
+ __attribute__((noinline,noclone,used)) void func() { asm (""); }
+
+dummy(_ITM_beginTransaction)
+dummy(_ITM_commitTransaction)
+dummy(_ITM_WU4)
+dummy(_ITM_WU8)
+dummy(_ITM_registerTMCloneTable)
+dummy(_ITM_deregisterTMCloneTable)
+
+main()
+{
+ __transaction_relaxed
+ {
+ foobar();
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/lto/trans-mem-2_1.c b/gcc/testsuite/gcc.dg/lto/trans-mem-2_1.c
new file mode 100644
index 00000000000..fb6918d6584
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/trans-mem-2_1.c
@@ -0,0 +1,4 @@
+__attribute__((transaction_callable,noinline))
+void foobar()
+{
+}
diff --git a/gcc/testsuite/gcc.dg/pr43864-2.c b/gcc/testsuite/gcc.dg/pr43864-2.c
index 1a0d9491a17..f00fff9fa91 100644
--- a/gcc/testsuite/gcc.dg/pr43864-2.c
+++ b/gcc/testsuite/gcc.dg/pr43864-2.c
@@ -19,4 +19,5 @@ f (int c, int b, int d)
/* { dg-final { scan-tree-dump-times "if " 0 "pre"} } */
/* { dg-final { scan-tree-dump-times "_.*\\\+.*_" 1 "pre"} } */
+/* { dg-final { scan-tree-dump-not "Invalid sum" "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/pr43864-3.c b/gcc/testsuite/gcc.dg/pr43864-3.c
index 622a5649541..c4954e1bd72 100644
--- a/gcc/testsuite/gcc.dg/pr43864-3.c
+++ b/gcc/testsuite/gcc.dg/pr43864-3.c
@@ -20,4 +20,5 @@ int f(int c, int b, int d)
/* { dg-final { scan-tree-dump-times "if " 0 "pre"} } */
/* { dg-final { scan-tree-dump-times "_.*\\\+.*_" 1 "pre"} } */
+/* { dg-final { scan-tree-dump-not "Invalid sum" "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/pr43864-4.c b/gcc/testsuite/gcc.dg/pr43864-4.c
index 3e3d643947d..42adfeefe95 100644
--- a/gcc/testsuite/gcc.dg/pr43864-4.c
+++ b/gcc/testsuite/gcc.dg/pr43864-4.c
@@ -25,4 +25,5 @@ int f(int c, int b, int d)
/* { dg-final { scan-tree-dump-times "if " 0 "pre"} } */
/* { dg-final { scan-tree-dump-times "_.*\\\+.*_" 1 "pre"} } */
/* { dg-final { scan-tree-dump-times " - " 2 "pre"} } */
+/* { dg-final { scan-tree-dump-not "Invalid sum" "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/pr43864.c b/gcc/testsuite/gcc.dg/pr43864.c
index 03c2d49c0fc..8d1e989fb18 100644
--- a/gcc/testsuite/gcc.dg/pr43864.c
+++ b/gcc/testsuite/gcc.dg/pr43864.c
@@ -32,4 +32,5 @@ hprofStartupp (char *outputFileName, char *ctx)
}
/* { dg-final { scan-tree-dump-times "myfree \\(" 1 "pre"} } */
+/* { dg-final { scan-tree-dump-not "Invalid sum" "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/pr50290.c b/gcc/testsuite/gcc.dg/pr50290.c
new file mode 100644
index 00000000000..47680fd9a72
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr50290.c
@@ -0,0 +1,27 @@
+/* PR rtl-optimization/50290 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-tree-loop-optimize -fno-tree-vrp -funroll-loops" } */
+
+static int
+bar (int t[], int b)
+{
+ int i;
+ for (i = 0; i < b; i++)
+ t[i] = i + (i > 0 ? t[i - 1] : 0);
+ return t[b - 1];
+}
+
+static int
+foo (int b)
+{
+ int x[b];
+ return bar (x, b);
+}
+
+int
+main ()
+{
+ if (foo (6) != 15)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr50764.c b/gcc/testsuite/gcc.dg/pr50764.c
new file mode 100644
index 00000000000..e3b8da8670f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr50764.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fsched2-use-superblocks -ftree-tail-merge" } */
+
+typedef int aligned __attribute__ ((aligned (64)));
+extern void abort (void);
+
+int bar (void *p);
+
+void
+foo (void)
+{
+ char *p = __builtin_alloca (13);
+ aligned i;
+
+ if (bar (p) || bar (&i))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/pr50765.c b/gcc/testsuite/gcc.dg/pr50765.c
new file mode 100644
index 00000000000..6e1c6974750
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr50765.c
@@ -0,0 +1,10 @@
+/* PR tree-optimization/50765 */
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-tree-dce" } */
+
+void
+foo (long *w, long *x, unsigned char *y, int z)
+{
+ for (; z < 429; z++)
+ w[z] = (-19 ^ y[z]) & x[z];
+}
diff --git a/gcc/testsuite/gcc.dg/pr50827.c b/gcc/testsuite/gcc.dg/pr50827.c
new file mode 100644
index 00000000000..5d258bfcf0a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr50827.c
@@ -0,0 +1,17 @@
+/* PR debug/50827 */
+/* { dg-do compile } */
+/* { dg-options "-g -O2 -funroll-loops" } */
+
+void
+foo (int w, int x, int *y, int *z)
+{
+ float f;
+ while (w--)
+ {
+ f = x;
+ if (y)
+ *y = (__INTPTR_TYPE__) y + w;
+ if (z)
+ *z = w;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pr51261.c b/gcc/testsuite/gcc.dg/pr51261.c
new file mode 100644
index 00000000000..b599a6b7db8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr51261.c
@@ -0,0 +1,9 @@
+/* PR target/51261 */
+/* { dg-do compile } */
+/* { dg-options "-fcompare-debug" } */
+
+void
+foo (void *p, int n)
+{
+ __builtin_memset (p, 0xff, n);
+}
diff --git a/gcc/testsuite/gcc.dg/simulate-thread/atomic-load-int128.c b/gcc/testsuite/gcc.dg/simulate-thread/atomic-load-int128.c
index 3ade0d6fad3..c5aa623e685 100644
--- a/gcc/testsuite/gcc.dg/simulate-thread/atomic-load-int128.c
+++ b/gcc/testsuite/gcc.dg/simulate-thread/atomic-load-int128.c
@@ -1,5 +1,5 @@
/* { dg-do link } */
-/* { dg-require-effective-target sync_int_128 } */
+/* { dg-require-effective-target sync_int_128_runtime } */
/* { dg-options "-mcx16" { target { x86_64-*-* i?86-*-* } } } */
/* { dg-final { simulate-thread } } */
diff --git a/gcc/testsuite/gcc.dg/simulate-thread/atomic-load-longlong.c b/gcc/testsuite/gcc.dg/simulate-thread/atomic-load-longlong.c
index 8bc2eaace65..91f9a062714 100644
--- a/gcc/testsuite/gcc.dg/simulate-thread/atomic-load-longlong.c
+++ b/gcc/testsuite/gcc.dg/simulate-thread/atomic-load-longlong.c
@@ -1,6 +1,7 @@
/* { dg-do link } */
-/* { dg-require-effective-target sync_long_long } */
+/* { dg-require-effective-target sync_long_long_runtime } */
/* { dg-options "" } */
+/* { dg-options "-march=pentium" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
/* { dg-final { simulate-thread } } */
diff --git a/gcc/testsuite/gcc.dg/simulate-thread/atomic-other-int128.c b/gcc/testsuite/gcc.dg/simulate-thread/atomic-other-int128.c
index 67f84a14a00..6aaaa88ef04 100644
--- a/gcc/testsuite/gcc.dg/simulate-thread/atomic-other-int128.c
+++ b/gcc/testsuite/gcc.dg/simulate-thread/atomic-other-int128.c
@@ -1,6 +1,6 @@
/* { dg-do link } */
-/* { dg-require-effective-target sync_int_128 } */
-/* { dg-options "-mcx16" { target { x86_64-*-* i?86-*-*] } } } */
+/* { dg-require-effective-target sync_int_128_runtime } */
+/* { dg-options "-mcx16" { target { x86_64-*-* i?86-*-* } } } */
/* { dg-final { simulate-thread } } */
#include <stdio.h>
diff --git a/gcc/testsuite/gcc.dg/simulate-thread/atomic-other-longlong.c b/gcc/testsuite/gcc.dg/simulate-thread/atomic-other-longlong.c
index ac4330bd8a4..087c4660cfb 100644
--- a/gcc/testsuite/gcc.dg/simulate-thread/atomic-other-longlong.c
+++ b/gcc/testsuite/gcc.dg/simulate-thread/atomic-other-longlong.c
@@ -1,6 +1,7 @@
/* { dg-do link } */
-/* { dg-require-effective-target sync_long_long } */
+/* { dg-require-effective-target sync_long_long_runtime } */
/* { dg-options "" } */
+/* { dg-options "-march=pentium" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
/* { dg-final { simulate-thread } } */
diff --git a/gcc/testsuite/gcc.dg/tm/20100615.c b/gcc/testsuite/gcc.dg/tm/20100615.c
index 3d9e4684e5d..26964d43367 100644
--- a/gcc/testsuite/gcc.dg/tm/20100615.c
+++ b/gcc/testsuite/gcc.dg/tm/20100615.c
@@ -3,7 +3,8 @@
/* Since the non TM version of new_node() gets optimized away, it
shouldn't appear in the clone table either. */
-/* { dg-final { scan-assembler-not "tm_clone_table" } } */
+/* { dg-final { scan-assembler-not "tm_clone_table" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler-not "__DATA,__tm_clone_table" { target *-*-darwin* } } } */
#define NULL 0
extern void *malloc (__SIZE_TYPE__);
diff --git a/gcc/testsuite/gcc.dg/tm/memopt-13.c b/gcc/testsuite/gcc.dg/tm/memopt-13.c
index 6e93b7feaea..381e682bca0 100644
--- a/gcc/testsuite/gcc.dg/tm/memopt-13.c
+++ b/gcc/testsuite/gcc.dg/tm/memopt-13.c
@@ -13,3 +13,4 @@ void f()
}
/* { dg-final { scan-tree-dump-times "memmoveRtWt \\\(&large_global," 1 "tmmark" } } */
+/* { dg-final { cleanup-tree-dump "tmmark" } } */
diff --git a/gcc/testsuite/gcc.dg/tm/memopt-6.c b/gcc/testsuite/gcc.dg/tm/memopt-6.c
index f4343736772..496ce2dd3e8 100644
--- a/gcc/testsuite/gcc.dg/tm/memopt-6.c
+++ b/gcc/testsuite/gcc.dg/tm/memopt-6.c
@@ -18,3 +18,4 @@ int f()
}
/* { dg-final { scan-tree-dump-times "memmoveRtWt \\\(&lala, &lacopy" 1 "tmedge" } } */
+/* { dg-final { cleanup-tree-dump "tmedge" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/fast-math-bb-slp-call-2.c b/gcc/testsuite/gcc.dg/vect/fast-math-bb-slp-call-2.c
index f555dfc9d8d..bf19fcd1594 100644
--- a/gcc/testsuite/gcc.dg/vect/fast-math-bb-slp-call-2.c
+++ b/gcc/testsuite/gcc.dg/vect/fast-math-bb-slp-call-2.c
@@ -1,3 +1,5 @@
+/* { dg-require-effective-target vect_double } */
+
#include "tree-vect.h"
extern long int lrint (double);
diff --git a/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-2.c b/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-2.c
index edb6670b028..ed7a9dceef7 100644
--- a/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-2.c
+++ b/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-2.c
@@ -1,3 +1,5 @@
+/* { dg-require-effective-target vect_double } */
+
#include "tree-vect.h"
extern long int lrint (double);
diff --git a/gcc/testsuite/gcc.dg/vect/pr30858.c b/gcc/testsuite/gcc.dg/vect/pr30858.c
index 0af2f8e9a91..0e7f7e10d4d 100644
--- a/gcc/testsuite/gcc.dg/vect/pr30858.c
+++ b/gcc/testsuite/gcc.dg/vect/pr30858.c
@@ -11,5 +11,5 @@ foo (int ko)
}
/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" } } */
-/* { dg-final { scan-tree-dump-times "Unknown def-use cycle pattern." 1 "vect" } } */
+/* { dg-final { scan-tree-dump "Unknown def-use cycle pattern." "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr51074.c b/gcc/testsuite/gcc.dg/vect/pr51074.c
new file mode 100644
index 00000000000..30913999400
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr51074.c
@@ -0,0 +1,24 @@
+/* PR tree-optimization/51074 */
+
+#include "tree-vect.h"
+
+struct S { int a, b; } s[8];
+
+int
+main ()
+{
+ int i;
+ check_vect ();
+ for (i = 0; i < 8; i++)
+ {
+ s[i].b = 0;
+ s[i].a = i;
+ }
+ asm volatile ("" : : : "memory");
+ for (i = 0; i < 8; i++)
+ if (s[i].b != 0 || s[i].a != i)
+ abort ();
+ return 0;
+}
+
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/volatile-bitfields-1.c b/gcc/testsuite/gcc.dg/volatile-bitfields-1.c
new file mode 100644
index 00000000000..6adda27fea4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/volatile-bitfields-1.c
@@ -0,0 +1,23 @@
+/* { dg-options "-fstrict-volatile-bitfields" } */
+/* { dg-do run } */
+
+extern int puts(const char *);
+extern void abort(void) __attribute__((noreturn));
+
+typedef struct {
+ volatile unsigned short a:8, b:8;
+} BitStruct;
+
+BitStruct bits = {1, 2};
+
+void check(int i, int j)
+{
+ if (i != 1 || j != 2) puts("FAIL"), abort();
+}
+
+int main ()
+{
+ check(bits.a, bits.b);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vshift-1.c b/gcc/testsuite/gcc.dg/vshift-1.c
index 2a237aa2bbe..2220ad5a4fd 100644
--- a/gcc/testsuite/gcc.dg/vshift-1.c
+++ b/gcc/testsuite/gcc.dg/vshift-1.c
@@ -94,10 +94,10 @@ main ()
for (i = 0; i < N; i++)
{
asm ("");
- c[i] = (random () << 1) | (random () & 1);
+ c[i] = (rand () << 1) | (rand () & 1);
b[i] = (i * 85) & (sizeof (TYPE1) * __CHAR_BIT__ - 1);
a[i] = c[i];
- d[i] = (random () << 1) | (random () & 1);
+ d[i] = (rand () << 1) | (rand () & 1);
d[i] |= (unsigned long long) c[i] << 32;
e[i] = (i * 85) & (sizeof (TYPE2) * __CHAR_BIT__ - 1);
f[i] = d[i];
diff --git a/gcc/testsuite/gcc.dg/vshift-3.c b/gcc/testsuite/gcc.dg/vshift-3.c
index e62c76b469f..367e6606551 100644
--- a/gcc/testsuite/gcc.dg/vshift-3.c
+++ b/gcc/testsuite/gcc.dg/vshift-3.c
@@ -100,9 +100,9 @@ main ()
for (i = 0; i < N; i++)
{
asm ("");
- c[i] = (random () << 1) | (random () & 1);
+ c[i] = (rand () << 1) | (rand () & 1);
a[i] = c[i];
- d[i] = (random () << 1) | (random () & 1);
+ d[i] = (rand () << 1) | (rand () & 1);
d[i] |= (unsigned long long) c[i] << 32;
f[i] = d[i];
}
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-13.c b/gcc/testsuite/gcc.misc-tests/gcov-13.c
index 605d4d4b382..14be8f9e103 100644
--- a/gcc/testsuite/gcc.misc-tests/gcov-13.c
+++ b/gcc/testsuite/gcc.misc-tests/gcov-13.c
@@ -16,3 +16,4 @@ int main ()
}
/* { dg-final { run-gcov { -a gcov-13.c } } } */
+/* { dg-final { run-gcov { -a gcovpart-13b.c } } } */
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-16.c b/gcc/testsuite/gcc.misc-tests/gcov-16.c
new file mode 100644
index 00000000000..478f44a367d
--- /dev/null
+++ b/gcc/testsuite/gcc.misc-tests/gcov-16.c
@@ -0,0 +1,12 @@
+/* Test visibility is copied */
+
+/* { dg-options "-fprofile-arcs -fvisibility=hidden" } */
+/* { dg-require-visibility "" } */
+/* { dg-require-weak "" } */
+
+void Foo ()
+{
+}
+
+ /* { dg-final { scan-assembler "\\.hidden\t__gcov__Foo" { target { ! *-*-darwin* } } } } */
+ /* { dg-final { scan-assembler "\\.private_extern ___gcov__Foo" { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-17.c b/gcc/testsuite/gcc.misc-tests/gcov-17.c
new file mode 100644
index 00000000000..f8ff794215c
--- /dev/null
+++ b/gcc/testsuite/gcc.misc-tests/gcov-17.c
@@ -0,0 +1,12 @@
+/* Test visibility is copied */
+
+/* { dg-options "-fprofile-arcs" } */
+/* { dg-require-visibility "" } */
+/* { dg-require-weak "" } */
+
+void __attribute__ ((visibility ("hidden"), weak)) Foo ()
+{
+}
+
+/* { dg-final { scan-assembler "\\.hidden\t__gcov__Foo" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "\\.private_extern ___gcov__Foo" { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/gcc.target/arm/pr49641.c b/gcc/testsuite/gcc.target/arm/pr49641.c
new file mode 100644
index 00000000000..7f9b3769c1a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr49641.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-mthumb -O2" } */
+/* { dg-require-effective-target arm_thumb1_ok } */
+/* { dg-final { scan-assembler-not "stmia\[\\t \]*r3!\[^\\n]*r3" } } */
+typedef struct {
+ void *t1, *t2, *t3;
+} z;
+extern volatile int y;
+static inline void foo(z *x) {
+ x->t1 = &x->t2;
+ x->t2 = ((void *)0);
+ x->t3 = &x->t1;
+}
+extern z v;
+void bar (void) {
+ y = 0;
+ foo(&v);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx-ceil-sfix-2-vec.c b/gcc/testsuite/gcc.target/i386/avx-ceil-sfix-2-vec.c
new file mode 100644
index 00000000000..bf48b80717b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-ceil-sfix-2-vec.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -mavx" } */
+/* { dg-require-effective-target avx } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#ifndef CHECK_H
+#define CHECK_H "avx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST avx_test
+#endif
+
+#include CHECK_H
+
+#include <math.h>
+
+extern double ceil (double);
+
+#define NUM 4
+
+static void
+__attribute__((__target__("fpmath=sse")))
+init_src (double *src)
+{
+ int i, sign = 1;
+ double f = rand ();
+
+ for (i = 0; i < NUM; i++)
+ {
+ src[i] = (i + 1) * f * M_PI * sign;
+ if (i < (NUM / 2))
+ {
+ if ((i % 6) == 0)
+ f = f * src[i];
+ }
+ else if (i == (NUM / 2))
+ f = rand ();
+ else if ((i % 6) == 0)
+ f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
+ sign = -sign;
+ }
+}
+
+static void
+__attribute__((__target__("fpmath=387")))
+TEST (void)
+{
+ double a[NUM];
+ int r[NUM];
+ int i;
+
+ init_src (a);
+
+ for (i = 0; i < NUM; i++)
+ r[i] = (int) ceil (a[i]);
+
+ /* check results: */
+ for (i = 0; i < NUM; i++)
+ if (r[i] != (int) ceil (a[i]))
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx-ceil-sfix-vec.c b/gcc/testsuite/gcc.target/i386/avx-ceil-sfix-vec.c
new file mode 100644
index 00000000000..ac0911fe844
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-ceil-sfix-vec.c
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -mavx" } */
+/* { dg-require-effective-target avx } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
+
+#include "sse4_1-ceil-sfix-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-ceil-vec.c b/gcc/testsuite/gcc.target/i386/avx-ceil-vec.c
index e917e31b4ef..0e76ab8026c 100644
--- a/gcc/testsuite/gcc.target/i386/avx-ceil-vec.c
+++ b/gcc/testsuite/gcc.target/i386/avx-ceil-vec.c
@@ -3,52 +3,7 @@
/* { dg-require-effective-target avx } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "avx-check.h"
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
-#include <math.h>
-
-extern double ceil (double);
-
-#define NUM 64
-
-static void
-__attribute__((__target__("fpmath=sse")))
-init_src (double *src)
-{
- int i, sign = 1;
- double f = rand ();
-
- for (i = 0; i < NUM; i++)
- {
- src[i] = (i + 1) * f * M_PI * sign;
- if (i < (NUM / 2))
- {
- if ((i % 6) == 0)
- f = f * src[i];
- }
- else if (i == (NUM / 2))
- f = rand ();
- else if ((i % 6) == 0)
- f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
- sign = -sign;
- }
-}
-
-static void
-__attribute__((__target__("fpmath=387")))
-avx_test (void)
-{
- double a[NUM];
- double r[NUM];
- int i;
-
- init_src (a);
-
- for (i = 0; i < NUM; i++)
- r[i] = ceil (a[i]);
-
- /* check results: */
- for (i = 0; i < NUM; i++)
- if (r[i] != ceil (a[i]))
- abort();
-}
+#include "sse4_1-ceil-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-ceilf-sfix-vec.c b/gcc/testsuite/gcc.target/i386/avx-ceilf-sfix-vec.c
new file mode 100644
index 00000000000..789b78e76a7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-ceilf-sfix-vec.c
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -mavx" } */
+/* { dg-require-effective-target avx } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
+
+#include "sse4_1-ceilf-sfix-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-ceilf-vec.c b/gcc/testsuite/gcc.target/i386/avx-ceilf-vec.c
index ef316214d8a..c324a9b4f4f 100644
--- a/gcc/testsuite/gcc.target/i386/avx-ceilf-vec.c
+++ b/gcc/testsuite/gcc.target/i386/avx-ceilf-vec.c
@@ -3,52 +3,7 @@
/* { dg-require-effective-target avx } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "avx-check.h"
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
-#include <math.h>
-
-extern float ceilf (float);
-
-#define NUM 64
-
-static void
-__attribute__((__target__("fpmath=sse")))
-init_src (float *src)
-{
- int i, sign = 1;
- float f = rand ();
-
- for (i = 0; i < NUM; i++)
- {
- src[i] = (i + 1) * f * M_PI * sign;
- if (i < (NUM / 2))
- {
- if ((i % 6) == 0)
- f = f * src[i];
- }
- else if (i == (NUM / 2))
- f = rand ();
- else if ((i % 6) == 0)
- f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
- sign = -sign;
- }
-}
-
-static void
-__attribute__((__target__("fpmath=387")))
-avx_test (void)
-{
- float a[NUM];
- float r[NUM];
- int i;
-
- init_src (a);
-
- for (i = 0; i < NUM; i++)
- r[i] = ceilf (a[i]);
-
- /* check results: */
- for (i = 0; i < NUM; i++)
- if (r[i] != ceilf (a[i]))
- abort();
-}
+#include "sse4_1-ceilf-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-copysign-vec.c b/gcc/testsuite/gcc.target/i386/avx-copysign-vec.c
index 130c4066be8..9b45a093a76 100644
--- a/gcc/testsuite/gcc.target/i386/avx-copysign-vec.c
+++ b/gcc/testsuite/gcc.target/i386/avx-copysign-vec.c
@@ -2,26 +2,7 @@
/* { dg-require-effective-target avx } */
/* { dg-options "-O2 -ftree-vectorize -mavx -mtune=generic" } */
-#include "avx-check.h"
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
-extern double copysign (double, double);
-
-#define N 16
-
-double a[N] = {-0.1,-3.2,-6.3,-9.4,-12.5,-15.6,-18.7,-21.8,24.9,27.1,30.2,33.3,36.4,39.5,42.6,45.7};
-double b[N] = {-1.2,3.4,-5.6,7.8,-9.0,1.0,-2.0,3.0,-4.0,-5.0,6.0,7.0,-8.0,-9.0,10.0,11.0};
-double r[N];
-
-static void
-avx_test (void)
-{
- int i;
-
- for (i = 0; i < N; i++)
- r[i] = copysign (a[i], b[i]);
-
- /* check results: */
- for (i = 0; i < N; i++)
- if (r[i] != copysign (a[i], b[i]))
- abort ();
-}
+#include "sse2-copysign-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-copysignf-vec.c b/gcc/testsuite/gcc.target/i386/avx-copysignf-vec.c
index 9ed3ab727cb..00aa6f57ffa 100644
--- a/gcc/testsuite/gcc.target/i386/avx-copysignf-vec.c
+++ b/gcc/testsuite/gcc.target/i386/avx-copysignf-vec.c
@@ -2,26 +2,7 @@
/* { dg-require-effective-target avx } */
/* { dg-options "-O2 -ftree-vectorize -mavx -mtune=generic" } */
-#include "avx-check.h"
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
-extern float copysignf (float, float);
-
-#define N 16
-
-float a[N] = {-0.1f,-3.2f,-6.3f,-9.4f,-12.5f,-15.6f,-18.7f,-21.8f,24.9f,27.1f,30.2f,33.3f,36.4f,39.5f,42.6f,45.7f};
-float b[N] = {-1.2f,3.4f,-5.6f,7.8f,-9.0f,1.0f,-2.0f,3.0f,-4.0f,-5.0f,6.0f,7.0f,-8.0f,-9.0f,10.0f,11.0f};
-float r[N];
-
-static void
-avx_test (void)
-{
- int i;
-
- for (i = 0; i < N; i++)
- r[i] = copysignf (a[i], b[i]);
-
- /* check results: */
- for (i = 0; i < N; i++)
- if (r[i] != copysignf (a[i], b[i]))
- abort ();
-}
+#include "sse-copysignf-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-cvt-2-vec.c b/gcc/testsuite/gcc.target/i386/avx-cvt-2-vec.c
new file mode 100644
index 00000000000..0081dcf3812
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-cvt-2-vec.c
@@ -0,0 +1,60 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -mavx" } */
+/* { dg-require-effective-target avx } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#ifndef CHECK_H
+#define CHECK_H "avx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST avx_test
+#endif
+
+#include CHECK_H
+
+#include <math.h>
+
+#define NUM 4
+
+static void
+__attribute__((__target__("fpmath=sse")))
+init_src (double *src)
+{
+ int i, sign = 1;
+ double f = rand ();
+
+ for (i = 0; i < NUM; i++)
+ {
+ src[i] = (i + 1) * f * M_PI * sign;
+ if (i < (NUM / 2))
+ {
+ if ((i % 6) == 0)
+ f = f * src[i];
+ }
+ else if (i == (NUM / 2))
+ f = rand ();
+ else if ((i % 6) == 0)
+ f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
+ sign = -sign;
+ }
+}
+
+static void
+__attribute__((__target__("fpmath=sse")))
+TEST (void)
+{
+ double a[NUM];
+ float r[NUM];
+ int i;
+
+ init_src (a);
+
+ for (i = 0; i < NUM; i++)
+ r[i] = (float) a[i];
+
+ /* check results: */
+ for (i = 0; i < NUM; i++)
+ if (r[i] != (float) a[i])
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx-cvt-vec.c b/gcc/testsuite/gcc.target/i386/avx-cvt-vec.c
new file mode 100644
index 00000000000..4dcfa398954
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-cvt-vec.c
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -mavx" } */
+/* { dg-require-effective-target avx } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
+
+#include "sse2-cvt-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-floor-sfix-2-vec.c b/gcc/testsuite/gcc.target/i386/avx-floor-sfix-2-vec.c
new file mode 100644
index 00000000000..275199cf8f0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-floor-sfix-2-vec.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -mavx" } */
+/* { dg-require-effective-target avx } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#ifndef CHECK_H
+#define CHECK_H "avx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST avx_test
+#endif
+
+#include CHECK_H
+
+#include <math.h>
+
+extern double floor (double);
+
+#define NUM 4
+
+static void
+__attribute__((__target__("fpmath=sse")))
+init_src (double *src)
+{
+ int i, sign = 1;
+ double f = rand ();
+
+ for (i = 0; i < NUM; i++)
+ {
+ src[i] = (i + 1) * f * M_PI * sign;
+ if (i < (NUM / 2))
+ {
+ if ((i % 6) == 0)
+ f = f * src[i];
+ }
+ else if (i == (NUM / 2))
+ f = rand ();
+ else if ((i % 6) == 0)
+ f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
+ sign = -sign;
+ }
+}
+
+static void
+__attribute__((__target__("fpmath=387")))
+TEST (void)
+{
+ double a[NUM];
+ int r[NUM];
+ int i;
+
+ init_src (a);
+
+ for (i = 0; i < NUM; i++)
+ r[i] = (int) floor (a[i]);
+
+ /* check results: */
+ for (i = 0; i < NUM; i++)
+ if (r[i] != (int) floor (a[i]))
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx-floor-sfix-vec.c b/gcc/testsuite/gcc.target/i386/avx-floor-sfix-vec.c
new file mode 100644
index 00000000000..efa557cf791
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-floor-sfix-vec.c
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -mavx" } */
+/* { dg-require-effective-target avx } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
+
+#include "sse4_1-floor-sfix-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-floor-vec.c b/gcc/testsuite/gcc.target/i386/avx-floor-vec.c
index 55f8f14c090..1d7fe504317 100644
--- a/gcc/testsuite/gcc.target/i386/avx-floor-vec.c
+++ b/gcc/testsuite/gcc.target/i386/avx-floor-vec.c
@@ -3,52 +3,7 @@
/* { dg-require-effective-target avx } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "avx-check.h"
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
-#include <math.h>
-
-extern double floor (double);
-
-#define NUM 64
-
-static void
-__attribute__((__target__("fpmath=sse")))
-init_src (double *src)
-{
- int i, sign = 1;
- double f = rand ();
-
- for (i = 0; i < NUM; i++)
- {
- src[i] = (i + 1) * f * M_PI * sign;
- if (i < (NUM / 2))
- {
- if ((i % 6) == 0)
- f = f * src[i];
- }
- else if (i == (NUM / 2))
- f = rand ();
- else if ((i % 6) == 0)
- f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
- sign = -sign;
- }
-}
-
-static void
-__attribute__((__target__("fpmath=387")))
-avx_test (void)
-{
- double a[NUM];
- double r[NUM];
- int i;
-
- init_src (a);
-
- for (i = 0; i < NUM; i++)
- r[i] = floor (a[i]);
-
- /* check results: */
- for (i = 0; i < NUM; i++)
- if (r[i] != floor (a[i]))
- abort();
-}
+#include "sse4_1-floor-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-floorf-sfix-vec.c b/gcc/testsuite/gcc.target/i386/avx-floorf-sfix-vec.c
new file mode 100644
index 00000000000..0c1587a1209
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-floorf-sfix-vec.c
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -mavx" } */
+/* { dg-require-effective-target avx } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
+
+#include "sse4_1-floorf-sfix-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-floorf-vec.c b/gcc/testsuite/gcc.target/i386/avx-floorf-vec.c
index 00348114c8c..73da85be9e1 100644
--- a/gcc/testsuite/gcc.target/i386/avx-floorf-vec.c
+++ b/gcc/testsuite/gcc.target/i386/avx-floorf-vec.c
@@ -3,52 +3,7 @@
/* { dg-require-effective-target avx } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "avx-check.h"
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
-#include <math.h>
-
-extern float floorf (float);
-
-#define NUM 64
-
-static void
-__attribute__((__target__("fpmath=sse")))
-init_src (float *src)
-{
- int i, sign = 1;
- float f = rand ();
-
- for (i = 0; i < NUM; i++)
- {
- src[i] = (i + 1) * f * M_PI * sign;
- if (i < (NUM / 2))
- {
- if ((i % 6) == 0)
- f = f * src[i];
- }
- else if (i == (NUM / 2))
- f = rand ();
- else if ((i % 6) == 0)
- f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
- sign = -sign;
- }
-}
-
-static void
-__attribute__((__target__("fpmath=387")))
-avx_test (void)
-{
- float a[NUM];
- float r[NUM];
- int i;
-
- init_src (a);
-
- for (i = 0; i < NUM; i++)
- r[i] = floorf (a[i]);
-
- /* check results: */
- for (i = 0; i < NUM; i++)
- if (r[i] != floorf (a[i]))
- abort();
-}
+#include "sse4_1-floorf-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-lrint-vec.c b/gcc/testsuite/gcc.target/i386/avx-lrint-vec.c
new file mode 100644
index 00000000000..2df65d2035d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-lrint-vec.c
@@ -0,0 +1,8 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -mavx" } */
+/* { dg-require-effective-target avx } */
+
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
+
+#include "sse2-lrint-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-lrintf-vec.c b/gcc/testsuite/gcc.target/i386/avx-lrintf-vec.c
new file mode 100644
index 00000000000..e08b2f5657d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-lrintf-vec.c
@@ -0,0 +1,8 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -mavx" } */
+/* { dg-require-effective-target avx } */
+
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
+
+#include "sse2-lrintf-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-recip-vec.c b/gcc/testsuite/gcc.target/i386/avx-recip-vec.c
new file mode 100644
index 00000000000..efeff7ece83
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-recip-vec.c
@@ -0,0 +1,8 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -mavx -mfpmath=sse -mrecip" } */
+/* { dg-require-effective-target avx } */
+
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
+
+#include "sse-recip-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-rint-sfix-2-vec.c b/gcc/testsuite/gcc.target/i386/avx-rint-sfix-2-vec.c
new file mode 100644
index 00000000000..9f273af5cbb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-rint-sfix-2-vec.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -mavx" } */
+/* { dg-require-effective-target avx } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#ifndef CHECK_H
+#define CHECK_H "avx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST avx_test
+#endif
+
+#include CHECK_H
+
+#include <math.h>
+
+extern double rint (double);
+
+#define NUM 4
+
+static void
+__attribute__((__target__("fpmath=sse")))
+init_src (double *src)
+{
+ int i, sign = 1;
+ double f = rand ();
+
+ for (i = 0; i < NUM; i++)
+ {
+ src[i] = (i + 1) * f * M_PI * sign;
+ if (i < (NUM / 2))
+ {
+ if ((i % 6) == 0)
+ f = f * src[i];
+ }
+ else if (i == (NUM / 2))
+ f = rand ();
+ else if ((i % 6) == 0)
+ f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
+ sign = -sign;
+ }
+}
+
+static void
+__attribute__((__target__("fpmath=387")))
+TEST (void)
+{
+ double a[NUM];
+ int r[NUM];
+ int i;
+
+ init_src (a);
+
+ for (i = 0; i < NUM; i++)
+ r[i] = (int) rint (a[i]);
+
+ /* check results: */
+ for (i = 0; i < NUM; i++)
+ if (r[i] != (int) rint (a[i]))
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx-rint-sfix-vec.c b/gcc/testsuite/gcc.target/i386/avx-rint-sfix-vec.c
new file mode 100644
index 00000000000..824f2eb7d52
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-rint-sfix-vec.c
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -mavx" } */
+/* { dg-require-effective-target avx } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
+
+#include "sse4_1-rint-sfix-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-rint-vec.c b/gcc/testsuite/gcc.target/i386/avx-rint-vec.c
index dc8c61017c3..c1d420c6c36 100644
--- a/gcc/testsuite/gcc.target/i386/avx-rint-vec.c
+++ b/gcc/testsuite/gcc.target/i386/avx-rint-vec.c
@@ -3,52 +3,7 @@
/* { dg-require-effective-target avx } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "avx-check.h"
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
-#include <math.h>
-
-extern double rint (double);
-
-#define NUM 64
-
-static void
-__attribute__((__target__("fpmath=sse")))
-init_src (double *src)
-{
- int i, sign = 1;
- double f = rand ();
-
- for (i = 0; i < NUM; i++)
- {
- src[i] = (i + 1) * f * M_PI * sign;
- if (i < (NUM / 2))
- {
- if ((i % 6) == 0)
- f = f * src[i];
- }
- else if (i == (NUM / 2))
- f = rand ();
- else if ((i % 6) == 0)
- f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
- sign = -sign;
- }
-}
-
-static void
-__attribute__((__target__("fpmath=387")))
-avx_test (void)
-{
- double a[NUM];
- double r[NUM];
- int i;
-
- init_src (a);
-
- for (i = 0; i < NUM; i++)
- r[i] = rint (a[i]);
-
- /* check results: */
- for (i = 0; i < NUM; i++)
- if (r[i] != rint (a[i]))
- abort();
-}
+#include "sse4_1-rint-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-rintf-sfix-vec.c b/gcc/testsuite/gcc.target/i386/avx-rintf-sfix-vec.c
new file mode 100644
index 00000000000..e5ddf790d75
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-rintf-sfix-vec.c
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -mavx" } */
+/* { dg-require-effective-target avx } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
+
+#include "sse4_1-rintf-sfix-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-rintf-vec.c b/gcc/testsuite/gcc.target/i386/avx-rintf-vec.c
index 4d77bf25b29..caf365da685 100644
--- a/gcc/testsuite/gcc.target/i386/avx-rintf-vec.c
+++ b/gcc/testsuite/gcc.target/i386/avx-rintf-vec.c
@@ -3,52 +3,7 @@
/* { dg-require-effective-target avx } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "avx-check.h"
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
-#include <math.h>
-
-extern float rintf (float);
-
-#define NUM 64
-
-static void
-__attribute__((__target__("fpmath=sse")))
-init_src (float *src)
-{
- int i, sign = 1;
- float f = rand ();
-
- for (i = 0; i < NUM; i++)
- {
- src[i] = (i + 1) * f * M_PI * sign;
- if (i < (NUM / 2))
- {
- if ((i % 6) == 0)
- f = f * src[i];
- }
- else if (i == (NUM / 2))
- f = rand ();
- else if ((i % 6) == 0)
- f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
- sign = -sign;
- }
-}
-
-static void
-__attribute__((__target__("fpmath=387")))
-avx_test (void)
-{
- float a[NUM];
- float r[NUM];
- int i;
-
- init_src (a);
-
- for (i = 0; i < NUM; i++)
- r[i] = rintf (a[i]);
-
- /* check results: */
- for (i = 0; i < NUM; i++)
- if (r[i] != rintf (a[i]))
- abort();
-}
+#include "sse4_1-rintf-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-round-sfix-2-vec.c b/gcc/testsuite/gcc.target/i386/avx-round-sfix-2-vec.c
new file mode 100644
index 00000000000..ddb46d9252a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-round-sfix-2-vec.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -mavx" } */
+/* { dg-require-effective-target avx } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#ifndef CHECK_H
+#define CHECK_H "avx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST avx_test
+#endif
+
+#include CHECK_H
+
+#include <math.h>
+
+extern double round (double);
+
+#define NUM 4
+
+static void
+__attribute__((__target__("fpmath=sse")))
+init_src (double *src)
+{
+ int i, sign = 1;
+ double f = rand ();
+
+ for (i = 0; i < NUM; i++)
+ {
+ src[i] = (i + 1) * f * M_PI * sign;
+ if (i < (NUM / 2))
+ {
+ if ((i % 6) == 0)
+ f = f * src[i];
+ }
+ else if (i == (NUM / 2))
+ f = rand ();
+ else if ((i % 6) == 0)
+ f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
+ sign = -sign;
+ }
+}
+
+static void
+__attribute__((__target__("fpmath=387")))
+TEST (void)
+{
+ double a[NUM];
+ int r[NUM];
+ int i;
+
+ init_src (a);
+
+ for (i = 0; i < NUM; i++)
+ r[i] = (int) round (a[i]);
+
+ /* check results: */
+ for (i = 0; i < NUM; i++)
+ if (r[i] != (int) round (a[i]))
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx-round-sfix-vec.c b/gcc/testsuite/gcc.target/i386/avx-round-sfix-vec.c
new file mode 100644
index 00000000000..5adfffa5f10
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-round-sfix-vec.c
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -mavx" } */
+/* { dg-require-effective-target avx } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
+
+#include "sse4_1-round-sfix-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-round-vec.c b/gcc/testsuite/gcc.target/i386/avx-round-vec.c
index 4cfb11ba7cd..c43c057049d 100644
--- a/gcc/testsuite/gcc.target/i386/avx-round-vec.c
+++ b/gcc/testsuite/gcc.target/i386/avx-round-vec.c
@@ -3,52 +3,7 @@
/* { dg-require-effective-target avx } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "avx-check.h"
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
-#include <math.h>
-
-extern double round (double);
-
-#define NUM 64
-
-static void
-__attribute__((__target__("fpmath=sse")))
-init_src (double *src)
-{
- int i, sign = 1;
- double f = rand ();
-
- for (i = 0; i < NUM; i++)
- {
- src[i] = (i + 1) * f * M_PI * sign;
- if (i < (NUM / 2))
- {
- if ((i % 6) == 0)
- f = f * src[i];
- }
- else if (i == (NUM / 2))
- f = rand ();
- else if ((i % 6) == 0)
- f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
- sign = -sign;
- }
-}
-
-static void
-__attribute__((__target__("fpmath=387")))
-avx_test (void)
-{
- double a[NUM];
- double r[NUM];
- int i;
-
- init_src (a);
-
- for (i = 0; i < NUM; i++)
- r[i] = round (a[i]);
-
- /* check results: */
- for (i = 0; i < NUM; i++)
- if (r[i] != round (a[i]))
- abort();
-}
+#include "sse4_1-round-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-roundf-sfix-vec.c b/gcc/testsuite/gcc.target/i386/avx-roundf-sfix-vec.c
new file mode 100644
index 00000000000..1fd4591233d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-roundf-sfix-vec.c
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -mavx" } */
+/* { dg-require-effective-target avx } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
+
+#include "sse4_1-roundf-sfix-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-roundf-vec.c b/gcc/testsuite/gcc.target/i386/avx-roundf-vec.c
index ec4c16691c2..978013eb126 100644
--- a/gcc/testsuite/gcc.target/i386/avx-roundf-vec.c
+++ b/gcc/testsuite/gcc.target/i386/avx-roundf-vec.c
@@ -3,52 +3,7 @@
/* { dg-require-effective-target avx } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "avx-check.h"
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
-#include <math.h>
-
-extern float roundf (float);
-
-#define NUM 64
-
-static void
-__attribute__((__target__("fpmath=sse")))
-init_src (float *src)
-{
- int i, sign = 1;
- float f = rand ();
-
- for (i = 0; i < NUM; i++)
- {
- src[i] = (i + 1) * f * M_PI * sign;
- if (i < (NUM / 2))
- {
- if ((i % 6) == 0)
- f = f * src[i];
- }
- else if (i == (NUM / 2))
- f = rand ();
- else if ((i % 6) == 0)
- f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
- sign = -sign;
- }
-}
-
-static void
-__attribute__((__target__("fpmath=387")))
-avx_test (void)
-{
- float a[NUM];
- float r[NUM];
- int i;
-
- init_src (a);
-
- for (i = 0; i < NUM; i++)
- r[i] = roundf (a[i]);
-
- /* check results: */
- for (i = 0; i < NUM; i++)
- if (r[i] != roundf (a[i]))
- abort();
-}
+#include "sse4_1-roundf-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-trunc-vec.c b/gcc/testsuite/gcc.target/i386/avx-trunc-vec.c
index 0b37eb4e04a..a1ee6d461f3 100644
--- a/gcc/testsuite/gcc.target/i386/avx-trunc-vec.c
+++ b/gcc/testsuite/gcc.target/i386/avx-trunc-vec.c
@@ -3,52 +3,7 @@
/* { dg-require-effective-target avx } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "avx-check.h"
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
-#include <math.h>
-
-extern double trunc (double);
-
-#define NUM 64
-
-static void
-__attribute__((__target__("fpmath=sse")))
-init_src (double *src)
-{
- int i, sign = 1;
- double f = rand ();
-
- for (i = 0; i < NUM; i++)
- {
- src[i] = (i + 1) * f * M_PI * sign;
- if (i < (NUM / 2))
- {
- if ((i % 6) == 0)
- f = f * src[i];
- }
- else if (i == (NUM / 2))
- f = rand ();
- else if ((i % 6) == 0)
- f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
- sign = -sign;
- }
-}
-
-static void
-__attribute__((__target__("fpmath=387")))
-avx_test (void)
-{
- double a[NUM];
- double r[NUM];
- int i;
-
- init_src (a);
-
- for (i = 0; i < NUM; i++)
- r[i] = trunc (a[i]);
-
- /* check results: */
- for (i = 0; i < NUM; i++)
- if (r[i] != trunc (a[i]))
- abort();
-}
+#include "sse4_1-truncf-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-truncf-vec.c b/gcc/testsuite/gcc.target/i386/avx-truncf-vec.c
index 099ff824624..a1ee6d461f3 100644
--- a/gcc/testsuite/gcc.target/i386/avx-truncf-vec.c
+++ b/gcc/testsuite/gcc.target/i386/avx-truncf-vec.c
@@ -3,52 +3,7 @@
/* { dg-require-effective-target avx } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "avx-check.h"
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
-#include <math.h>
-
-extern float truncf (float);
-
-#define NUM 64
-
-static void
-__attribute__((__target__("fpmath=sse")))
-init_src (float *src)
-{
- int i, sign = 1;
- float f = rand ();
-
- for (i = 0; i < NUM; i++)
- {
- src[i] = (i + 1) * f * M_PI * sign;
- if (i < (NUM / 2))
- {
- if ((i % 6) == 0)
- f = f * src[i];
- }
- else if (i == (NUM / 2))
- f = rand ();
- else if ((i % 6) == 0)
- f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
- sign = -sign;
- }
-}
-
-static void
-__attribute__((__target__("fpmath=387")))
-avx_test (void)
-{
- float a[NUM];
- float r[NUM];
- int i;
-
- init_src (a);
-
- for (i = 0; i < NUM; i++)
- r[i] = truncf (a[i]);
-
- /* check results: */
- for (i = 0; i < NUM; i++)
- if (r[i] != truncf (a[i]))
- abort();
-}
+#include "sse4_1-truncf-vec.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr51235.c b/gcc/testsuite/gcc.target/i386/pr51235.c
new file mode 100644
index 00000000000..c99d5c0e733
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr51235.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O -ftree-vectorize -mxop -mavx2" } */
+
+void *foo (int count, void **list)
+{
+ void *minaddr = list[0];
+ int i;
+
+ for (i = 1; i < count; i++)
+ {
+ void *addr = list[i];
+ if (addr < minaddr)
+ minaddr = addr;
+ }
+
+ return minaddr;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr51236.c b/gcc/testsuite/gcc.target/i386/pr51236.c
new file mode 100644
index 00000000000..63bfaeeb0eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr51236.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O -ftree-vectorize -mavx2" } */
+
+long foo (long *p, int i)
+{
+ long x = 0;
+
+ while (--i)
+ x ^= p[i];
+
+ return x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse-copysignf-vec.c b/gcc/testsuite/gcc.target/i386/sse-copysignf-vec.c
index bd85889503d..5b1cfe795f2 100644
--- a/gcc/testsuite/gcc.target/i386/sse-copysignf-vec.c
+++ b/gcc/testsuite/gcc.target/i386/sse-copysignf-vec.c
@@ -2,7 +2,15 @@
/* { dg-options "-O2 -ftree-vectorize -msse" } */
/* { dg-require-effective-target sse } */
-#include "sse-check.h"
+#ifndef CHECK_H
+#define CHECK_H "sse-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse_test
+#endif
+
+#include CHECK_H
extern float copysignf (float, float);
@@ -13,7 +21,7 @@ float b[N] = {-1.2f,3.4f,-5.6f,7.8f,-9.0f,1.0f,-2.0f,3.0f,-4.0f,-5.0f,6.0f,7.0f,
float r[N];
static void
-sse_test (void)
+TEST (void)
{
int i;
diff --git a/gcc/testsuite/gcc.target/i386/sse-recip-vec.c b/gcc/testsuite/gcc.target/i386/sse-recip-vec.c
index bb1e458f92d..de2f3d29775 100644
--- a/gcc/testsuite/gcc.target/i386/sse-recip-vec.c
+++ b/gcc/testsuite/gcc.target/i386/sse-recip-vec.c
@@ -2,7 +2,15 @@
/* { dg-options "-O2 -ffast-math -ftree-vectorize -msse -mfpmath=sse -mrecip" } */
/* { dg-require-effective-target sse } */
-#include "sse-check.h"
+#ifndef CHECK_H
+#define CHECK_H "sse-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse_test
+#endif
+
+#include CHECK_H
extern float sqrtf (float);
extern float fabsf (float);
@@ -16,7 +24,7 @@ float r[N];
float rc[N] = { 0.f, 3.f, 6.f, 9.f, 12.f, 18.f, 21.f, 27.f };
static void
-sse_test (void)
+TEST (void)
{
int i;
diff --git a/gcc/testsuite/gcc.target/i386/sse2-copysign-vec.c b/gcc/testsuite/gcc.target/i386/sse2-copysign-vec.c
index 5726448d76c..b336b3284d0 100644
--- a/gcc/testsuite/gcc.target/i386/sse2-copysign-vec.c
+++ b/gcc/testsuite/gcc.target/i386/sse2-copysign-vec.c
@@ -2,7 +2,15 @@
/* { dg-options "-O2 -ftree-vectorize -msse2" } */
/* { dg-require-effective-target sse2 } */
-#include "sse2-check.h"
+#ifndef CHECK_H
+#define CHECK_H "sse2-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse2_test
+#endif
+
+#include CHECK_H
extern double copysign (double, double);
@@ -13,7 +21,7 @@ double b[N] = {-1.2,3.4,-5.6,7.8,-9.0,1.0,-2.0,3.0,-4.0,-5.0,6.0,7.0,-8.0,-9.0,1
double r[N];
static void
-sse2_test (void)
+TEST (void)
{
int i;
diff --git a/gcc/testsuite/gcc.target/i386/sse2-cvt-vec.c b/gcc/testsuite/gcc.target/i386/sse2-cvt-vec.c
new file mode 100644
index 00000000000..8a811a3defe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-cvt-vec.c
@@ -0,0 +1,60 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -msse2" } */
+/* { dg-require-effective-target sse2 } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse2-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse2_test
+#endif
+
+#include CHECK_H
+
+#include <math.h>
+
+#define NUM 64
+
+static void
+__attribute__((__target__("fpmath=sse")))
+init_src (double *src)
+{
+ int i, sign = 1;
+ double f = rand ();
+
+ for (i = 0; i < NUM; i++)
+ {
+ src[i] = (i + 1) * f * M_PI * sign;
+ if (i < (NUM / 2))
+ {
+ if ((i % 6) == 0)
+ f = f * src[i];
+ }
+ else if (i == (NUM / 2))
+ f = rand ();
+ else if ((i % 6) == 0)
+ f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
+ sign = -sign;
+ }
+}
+
+static void
+__attribute__((__target__("fpmath=sse")))
+TEST (void)
+{
+ double a[NUM];
+ float r[NUM];
+ int i;
+
+ init_src (a);
+
+ for (i = 0; i < NUM; i++)
+ r[i] = (float) a[i];
+
+ /* check results: */
+ for (i = 0; i < NUM; i++)
+ if (r[i] != (float) a[i])
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-lrint-vec.c b/gcc/testsuite/gcc.target/i386/sse2-lrint-vec.c
index 43797f70782..111e9b2740e 100644
--- a/gcc/testsuite/gcc.target/i386/sse2-lrint-vec.c
+++ b/gcc/testsuite/gcc.target/i386/sse2-lrint-vec.c
@@ -2,7 +2,15 @@
/* { dg-options "-O2 -ffast-math -ftree-vectorize -msse2" } */
/* { dg-require-effective-target sse2 } */
-#include "sse2-check.h"
+#ifndef CHECK_H
+#define CHECK_H "sse2-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse2_test
+#endif
+
+#include CHECK_H
extern long lrint (double);
@@ -12,7 +20,7 @@ double a[N] = {0.4,3.5,6.6,9.4,12.5,15.6,18.4,21.5,24.6,27.4,30.5,33.6,36.4,39.5
long r[N];
static void
-sse2_test (void)
+TEST (void)
{
int i;
diff --git a/gcc/testsuite/gcc.target/i386/sse2-lrintf-vec.c b/gcc/testsuite/gcc.target/i386/sse2-lrintf-vec.c
index eaec22cb3a3..ee917623cbd 100644
--- a/gcc/testsuite/gcc.target/i386/sse2-lrintf-vec.c
+++ b/gcc/testsuite/gcc.target/i386/sse2-lrintf-vec.c
@@ -2,7 +2,15 @@
/* { dg-options "-O2 -ffast-math -ftree-vectorize -msse2" } */
/* { dg-require-effective-target sse2 } */
-#include "sse2-check.h"
+#ifndef CHECK_H
+#define CHECK_H "sse2-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse2_test
+#endif
+
+#include CHECK_H
extern long lrintf (float);
@@ -12,7 +20,7 @@ float a[N] = {0.4,3.5,6.6,9.4,12.5,15.6,18.4,21.5,24.6,27.4,30.5,33.6,36.4,39.5,
long r[N];
static void
-sse2_test (void)
+TEST (void)
{
int i;
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-ceil-sfix-vec.c b/gcc/testsuite/gcc.target/i386/sse4_1-ceil-sfix-vec.c
new file mode 100644
index 00000000000..ca07d9c003f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-ceil-sfix-vec.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -msse4.1" } */
+/* { dg-require-effective-target sse4 } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <math.h>
+
+extern double ceil (double);
+
+#define NUM 64
+
+static void
+__attribute__((__target__("fpmath=sse")))
+init_src (double *src)
+{
+ int i, sign = 1;
+ double f = rand ();
+
+ for (i = 0; i < NUM; i++)
+ {
+ src[i] = (i + 1) * f * M_PI * sign;
+ if (i < (NUM / 2))
+ {
+ if ((i % 6) == 0)
+ f = f * src[i];
+ }
+ else if (i == (NUM / 2))
+ f = rand ();
+ else if ((i % 6) == 0)
+ f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
+ sign = -sign;
+ }
+}
+
+static void
+__attribute__((__target__("fpmath=387")))
+TEST (void)
+{
+ double a[NUM];
+ int r[NUM];
+ int i;
+
+ init_src (a);
+
+ for (i = 0; i < NUM; i++)
+ r[i] = (int) ceil (a[i]);
+
+ /* check results: */
+ for (i = 0; i < NUM; i++)
+ if (r[i] != (int) ceil (a[i]))
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-ceil-vec.c b/gcc/testsuite/gcc.target/i386/sse4_1-ceil-vec.c
index 886dd77c206..20bb2641fac 100644
--- a/gcc/testsuite/gcc.target/i386/sse4_1-ceil-vec.c
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-ceil-vec.c
@@ -3,7 +3,15 @@
/* { dg-require-effective-target sse4 } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "sse4_1-check.h"
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
#include <math.h>
@@ -36,7 +44,7 @@ init_src (double *src)
static void
__attribute__((__target__("fpmath=387")))
-sse4_1_test (void)
+TEST (void)
{
double a[NUM];
double r[NUM];
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-ceilf-sfix-vec.c b/gcc/testsuite/gcc.target/i386/sse4_1-ceilf-sfix-vec.c
new file mode 100644
index 00000000000..b0559bf3995
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-ceilf-sfix-vec.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -msse4.1" } */
+/* { dg-require-effective-target sse4 } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <math.h>
+
+extern float ceilf (float);
+
+#define NUM 64
+
+static void
+__attribute__((__target__("fpmath=sse")))
+init_src (float *src)
+{
+ int i, sign = 1;
+ float f = rand ();
+
+ for (i = 0; i < NUM; i++)
+ {
+ src[i] = (i + 1) * f * M_PI * sign;
+ if (i < (NUM / 2))
+ {
+ if ((i % 6) == 0)
+ f = f * src[i];
+ }
+ else if (i == (NUM / 2))
+ f = rand ();
+ else if ((i % 6) == 0)
+ f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
+ sign = -sign;
+ }
+}
+
+static void
+__attribute__((__target__("fpmath=387")))
+TEST (void)
+{
+ float a[NUM];
+ int r[NUM];
+ int i;
+
+ init_src (a);
+
+ for (i = 0; i < NUM; i++)
+ r[i] = (int) ceilf (a[i]);
+
+ /* check results: */
+ for (i = 0; i < NUM; i++)
+ if (r[i] != (int) ceilf (a[i]))
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-ceilf-vec.c b/gcc/testsuite/gcc.target/i386/sse4_1-ceilf-vec.c
index 41d59d74eac..314be91fa6c 100644
--- a/gcc/testsuite/gcc.target/i386/sse4_1-ceilf-vec.c
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-ceilf-vec.c
@@ -3,7 +3,15 @@
/* { dg-require-effective-target sse4 } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "sse4_1-check.h"
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
#include <math.h>
@@ -36,7 +44,7 @@ init_src (float *src)
static void
__attribute__((__target__("fpmath=387")))
-sse4_1_test (void)
+TEST (void)
{
float a[NUM];
float r[NUM];
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-floor-sfix-vec.c b/gcc/testsuite/gcc.target/i386/sse4_1-floor-sfix-vec.c
new file mode 100644
index 00000000000..2083a60e7fe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-floor-sfix-vec.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -msse4.1" } */
+/* { dg-require-effective-target sse4 } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <math.h>
+
+extern double floor (double);
+
+#define NUM 64
+
+static void
+__attribute__((__target__("fpmath=sse")))
+init_src (double *src)
+{
+ int i, sign = 1;
+ double f = rand ();
+
+ for (i = 0; i < NUM; i++)
+ {
+ src[i] = (i + 1) * f * M_PI * sign;
+ if (i < (NUM / 2))
+ {
+ if ((i % 6) == 0)
+ f = f * src[i];
+ }
+ else if (i == (NUM / 2))
+ f = rand ();
+ else if ((i % 6) == 0)
+ f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
+ sign = -sign;
+ }
+}
+
+static void
+__attribute__((__target__("fpmath=387")))
+TEST (void)
+{
+ double a[NUM];
+ int r[NUM];
+ int i;
+
+ init_src (a);
+
+ for (i = 0; i < NUM; i++)
+ r[i] = (int) floor (a[i]);
+
+ /* check results: */
+ for (i = 0; i < NUM; i++)
+ if (r[i] != (int) floor (a[i]))
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-floor-vec.c b/gcc/testsuite/gcc.target/i386/sse4_1-floor-vec.c
index 02ebe62ec7b..d250413c1b7 100644
--- a/gcc/testsuite/gcc.target/i386/sse4_1-floor-vec.c
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-floor-vec.c
@@ -3,7 +3,15 @@
/* { dg-require-effective-target sse4 } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "sse4_1-check.h"
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
#include <math.h>
@@ -36,7 +44,7 @@ init_src (double *src)
static void
__attribute__((__target__("fpmath=387")))
-sse4_1_test (void)
+TEST (void)
{
double a[NUM];
double r[NUM];
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-floorf-sfix-vec.c b/gcc/testsuite/gcc.target/i386/sse4_1-floorf-sfix-vec.c
new file mode 100644
index 00000000000..aa2976d5b0a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-floorf-sfix-vec.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -msse4.1" } */
+/* { dg-require-effective-target sse4 } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <math.h>
+
+extern float floorf (float);
+
+#define NUM 64
+
+static void
+__attribute__((__target__("fpmath=sse")))
+init_src (float *src)
+{
+ int i, sign = 1;
+ float f = rand ();
+
+ for (i = 0; i < NUM; i++)
+ {
+ src[i] = (i + 1) * f * M_PI * sign;
+ if (i < (NUM / 2))
+ {
+ if ((i % 6) == 0)
+ f = f * src[i];
+ }
+ else if (i == (NUM / 2))
+ f = rand ();
+ else if ((i % 6) == 0)
+ f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
+ sign = -sign;
+ }
+}
+
+static void
+__attribute__((__target__("fpmath=387")))
+TEST (void)
+{
+ float a[NUM];
+ int r[NUM];
+ int i;
+
+ init_src (a);
+
+ for (i = 0; i < NUM; i++)
+ r[i] = (int) floorf (a[i]);
+
+ /* check results: */
+ for (i = 0; i < NUM; i++)
+ if (r[i] != (int) floorf (a[i]))
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-floorf-vec.c b/gcc/testsuite/gcc.target/i386/sse4_1-floorf-vec.c
index 6704892df53..2f339f3b50e 100644
--- a/gcc/testsuite/gcc.target/i386/sse4_1-floorf-vec.c
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-floorf-vec.c
@@ -3,7 +3,15 @@
/* { dg-require-effective-target sse4 } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "sse4_1-check.h"
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
#include <math.h>
@@ -36,7 +44,7 @@ init_src (float *src)
static void
__attribute__((__target__("fpmath=387")))
-sse4_1_test (void)
+TEST (void)
{
float a[NUM];
float r[NUM];
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-rint-sfix-vec.c b/gcc/testsuite/gcc.target/i386/sse4_1-rint-sfix-vec.c
new file mode 100644
index 00000000000..d9c2fbf2d37
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-rint-sfix-vec.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -msse4.1" } */
+/* { dg-require-effective-target sse4 } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <math.h>
+
+extern double rint (double);
+
+#define NUM 64
+
+static void
+__attribute__((__target__("fpmath=sse")))
+init_src (double *src)
+{
+ int i, sign = 1;
+ double f = rand ();
+
+ for (i = 0; i < NUM; i++)
+ {
+ src[i] = (i + 1) * f * M_PI * sign;
+ if (i < (NUM / 2))
+ {
+ if ((i % 6) == 0)
+ f = f * src[i];
+ }
+ else if (i == (NUM / 2))
+ f = rand ();
+ else if ((i % 6) == 0)
+ f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
+ sign = -sign;
+ }
+}
+
+static void
+__attribute__((__target__("fpmath=387")))
+TEST (void)
+{
+ double a[NUM];
+ int r[NUM];
+ int i;
+
+ init_src (a);
+
+ for (i = 0; i < NUM; i++)
+ r[i] = (int) rint (a[i]);
+
+ /* check results: */
+ for (i = 0; i < NUM; i++)
+ if (r[i] != (int) rint (a[i]))
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-rint-vec.c b/gcc/testsuite/gcc.target/i386/sse4_1-rint-vec.c
index 8df5717a23d..f20359a1ae2 100644
--- a/gcc/testsuite/gcc.target/i386/sse4_1-rint-vec.c
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-rint-vec.c
@@ -3,7 +3,15 @@
/* { dg-require-effective-target sse4 } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "sse4_1-check.h"
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
#include <math.h>
@@ -36,7 +44,7 @@ init_src (double *src)
static void
__attribute__((__target__("fpmath=387")))
-sse4_1_test (void)
+TEST (void)
{
double a[NUM];
double r[NUM];
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-rintf-sfix-vec.c b/gcc/testsuite/gcc.target/i386/sse4_1-rintf-sfix-vec.c
new file mode 100644
index 00000000000..1d25f7669d5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-rintf-sfix-vec.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -msse4.1" } */
+/* { dg-require-effective-target sse4 } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <math.h>
+
+extern float rintf (float);
+
+#define NUM 64
+
+static void
+__attribute__((__target__("fpmath=sse")))
+init_src (float *src)
+{
+ int i, sign = 1;
+ float f = rand ();
+
+ for (i = 0; i < NUM; i++)
+ {
+ src[i] = (i + 1) * f * M_PI * sign;
+ if (i < (NUM / 2))
+ {
+ if ((i % 6) == 0)
+ f = f * src[i];
+ }
+ else if (i == (NUM / 2))
+ f = rand ();
+ else if ((i % 6) == 0)
+ f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
+ sign = -sign;
+ }
+}
+
+static void
+__attribute__((__target__("fpmath=387")))
+TEST (void)
+{
+ float a[NUM];
+ int r[NUM];
+ int i;
+
+ init_src (a);
+
+ for (i = 0; i < NUM; i++)
+ r[i] = (int) rintf (a[i]);
+
+ /* check results: */
+ for (i = 0; i < NUM; i++)
+ if (r[i] != (int) rintf (a[i]))
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-rintf-vec.c b/gcc/testsuite/gcc.target/i386/sse4_1-rintf-vec.c
index 9c97c35bed9..716cad1e3ff 100644
--- a/gcc/testsuite/gcc.target/i386/sse4_1-rintf-vec.c
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-rintf-vec.c
@@ -3,7 +3,15 @@
/* { dg-require-effective-target sse4 } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "sse4_1-check.h"
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
#include <math.h>
@@ -36,7 +44,7 @@ init_src (float *src)
static void
__attribute__((__target__("fpmath=387")))
-sse4_1_test (void)
+TEST (void)
{
float a[NUM];
float r[NUM];
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-round-sfix-vec.c b/gcc/testsuite/gcc.target/i386/sse4_1-round-sfix-vec.c
new file mode 100644
index 00000000000..9abbe55b7d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-round-sfix-vec.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -msse4.1" } */
+/* { dg-require-effective-target sse4 } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <math.h>
+
+extern double round (double);
+
+#define NUM 64
+
+static void
+__attribute__((__target__("fpmath=sse")))
+init_src (double *src)
+{
+ int i, sign = 1;
+ double f = rand ();
+
+ for (i = 0; i < NUM; i++)
+ {
+ src[i] = (i + 1) * f * M_PI * sign;
+ if (i < (NUM / 2))
+ {
+ if ((i % 6) == 0)
+ f = f * src[i];
+ }
+ else if (i == (NUM / 2))
+ f = rand ();
+ else if ((i % 6) == 0)
+ f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
+ sign = -sign;
+ }
+}
+
+static void
+__attribute__((__target__("fpmath=387")))
+TEST (void)
+{
+ double a[NUM];
+ int r[NUM];
+ int i;
+
+ init_src (a);
+
+ for (i = 0; i < NUM; i++)
+ r[i] = (int) round (a[i]);
+
+ /* check results: */
+ for (i = 0; i < NUM; i++)
+ if (r[i] != (int) round (a[i]))
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-round-vec.c b/gcc/testsuite/gcc.target/i386/sse4_1-round-vec.c
index dcd36cd2b11..bb912cef955 100644
--- a/gcc/testsuite/gcc.target/i386/sse4_1-round-vec.c
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-round-vec.c
@@ -3,7 +3,15 @@
/* { dg-require-effective-target sse4 } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "sse4_1-check.h"
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
#include <math.h>
@@ -36,7 +44,7 @@ init_src (double *src)
static void
__attribute__((__target__("fpmath=387")))
-sse4_1_test (void)
+TEST (void)
{
double a[NUM];
double r[NUM];
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-roundf-sfix-vec.c b/gcc/testsuite/gcc.target/i386/sse4_1-roundf-sfix-vec.c
new file mode 100644
index 00000000000..5384e5c62c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-roundf-sfix-vec.c
@@ -0,0 +1,62 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math -ftree-vectorize -msse4.1" } */
+/* { dg-require-effective-target sse4 } */
+/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+#include <math.h>
+
+extern float roundf (float);
+
+#define NUM 64
+
+static void
+__attribute__((__target__("fpmath=sse")))
+init_src (float *src)
+{
+ int i, sign = 1;
+ float f = rand ();
+
+ for (i = 0; i < NUM; i++)
+ {
+ src[i] = (i + 1) * f * M_PI * sign;
+ if (i < (NUM / 2))
+ {
+ if ((i % 6) == 0)
+ f = f * src[i];
+ }
+ else if (i == (NUM / 2))
+ f = rand ();
+ else if ((i % 6) == 0)
+ f = 1 / (f * (i + 1) * src[i] * M_PI * sign);
+ sign = -sign;
+ }
+}
+
+static void
+__attribute__((__target__("fpmath=387")))
+TEST (void)
+{
+ float a[NUM];
+ int r[NUM];
+ int i;
+
+ init_src (a);
+
+ for (i = 0; i < NUM; i++)
+ r[i] = (int) roundf (a[i]);
+
+ /* check results: */
+ for (i = 0; i < NUM; i++)
+ if (r[i] != (int) roundf (a[i]))
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-roundf-vec.c b/gcc/testsuite/gcc.target/i386/sse4_1-roundf-vec.c
index d64660a1a91..d254aa66b89 100644
--- a/gcc/testsuite/gcc.target/i386/sse4_1-roundf-vec.c
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-roundf-vec.c
@@ -3,7 +3,15 @@
/* { dg-require-effective-target sse4 } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "sse4_1-check.h"
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
#include <math.h>
@@ -36,7 +44,7 @@ init_src (float *src)
static void
__attribute__((__target__("fpmath=387")))
-sse4_1_test (void)
+TEST (void)
{
float a[NUM];
float r[NUM];
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-trunc-vec.c b/gcc/testsuite/gcc.target/i386/sse4_1-trunc-vec.c
index e82dec93f88..9cbcd9b3985 100644
--- a/gcc/testsuite/gcc.target/i386/sse4_1-trunc-vec.c
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-trunc-vec.c
@@ -3,7 +3,15 @@
/* { dg-require-effective-target sse4 } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "sse4_1-check.h"
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
#include <math.h>
@@ -36,7 +44,7 @@ init_src (double *src)
static void
__attribute__((__target__("fpmath=387")))
-sse4_1_test (void)
+TEST (void)
{
double a[NUM];
double r[NUM];
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-truncf-vec.c b/gcc/testsuite/gcc.target/i386/sse4_1-truncf-vec.c
index 6a267ca94d6..815b5081433 100644
--- a/gcc/testsuite/gcc.target/i386/sse4_1-truncf-vec.c
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-truncf-vec.c
@@ -3,7 +3,15 @@
/* { dg-require-effective-target sse4 } */
/* { dg-skip-if "no M_PI" { vxworks_kernel } } */
-#include "sse4_1-check.h"
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
#include <math.h>
@@ -36,7 +44,7 @@ init_src (float *src)
static void
__attribute__((__target__("fpmath=387")))
-sse4_1_test (void)
+TEST (void)
{
float a[NUM];
float r[NUM];
diff --git a/gcc/testsuite/gcc.target/i386/sw-1.c b/gcc/testsuite/gcc.target/i386/sw-1.c
index e3d3b914860..483d117ecb7 100644
--- a/gcc/testsuite/gcc.target/i386/sw-1.c
+++ b/gcc/testsuite/gcc.target/i386/sw-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fshrink-wrap -fdump-rtl-pro_and_epilogue -mstringop-strategy=rep_byte" } */
+/* { dg-options "-O2 -fshrink-wrap -fdump-rtl-pro_and_epilogue" } */
#include <string.h>
diff --git a/gcc/testsuite/gcc.target/mips/div-1.c b/gcc/testsuite/gcc.target/mips/div-1.c
new file mode 100644
index 00000000000..e1976c25e0d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/div-1.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tddiv\t" } } */
+/* { dg-final { scan-assembler "\tmflo\t" } } */
+/* { dg-final { scan-assembler-not "\tmfhi\t" } } */
+
+typedef int DI __attribute__((mode(DI)));
+
+MIPS16 DI
+f (DI x, DI y)
+{
+ return x / y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/div-10.c b/gcc/testsuite/gcc.target/mips/div-10.c
new file mode 100644
index 00000000000..23075da2c3d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/div-10.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tdivu\t" } } */
+/* { dg-final { scan-assembler "\tmflo\t" } } */
+/* { dg-final { scan-assembler-not "\tmfhi\t" } } */
+
+typedef unsigned int SI __attribute__((mode(SI)));
+
+MIPS16 SI
+f (SI x, SI y)
+{
+ return x / y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/div-11.c b/gcc/testsuite/gcc.target/mips/div-11.c
new file mode 100644
index 00000000000..68f1658484b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/div-11.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tdiv\t" } } */
+/* { dg-final { scan-assembler-not "\tmflo\t" } } */
+/* { dg-final { scan-assembler "\tmfhi\t" } } */
+
+typedef int SI __attribute__((mode(SI)));
+
+MIPS16 SI
+f (SI x, SI y)
+{
+ return x % y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/div-12.c b/gcc/testsuite/gcc.target/mips/div-12.c
new file mode 100644
index 00000000000..c2384b20a9d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/div-12.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tdivu\t" } } */
+/* { dg-final { scan-assembler-not "\tmflo\t" } } */
+/* { dg-final { scan-assembler "\tmfhi\t" } } */
+
+typedef unsigned int SI __attribute__((mode(SI)));
+
+MIPS16 SI
+f (SI x, SI y)
+{
+ return x % y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/div-2.c b/gcc/testsuite/gcc.target/mips/div-2.c
new file mode 100644
index 00000000000..af6e2fa8e1a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/div-2.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tddivu\t" } } */
+/* { dg-final { scan-assembler "\tmflo\t" } } */
+/* { dg-final { scan-assembler-not "\tmfhi\t" } } */
+
+typedef unsigned int DI __attribute__((mode(DI)));
+
+MIPS16 DI
+f (DI x, DI y)
+{
+ return x / y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/div-3.c b/gcc/testsuite/gcc.target/mips/div-3.c
new file mode 100644
index 00000000000..684b6a8e441
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/div-3.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tddiv\t" } } */
+/* { dg-final { scan-assembler-not "\tmflo\t" } } */
+/* { dg-final { scan-assembler "\tmfhi\t" } } */
+
+typedef int DI __attribute__((mode(DI)));
+
+MIPS16 DI
+f (DI x, DI y)
+{
+ return x % y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/div-4.c b/gcc/testsuite/gcc.target/mips/div-4.c
new file mode 100644
index 00000000000..251b88f8164
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/div-4.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tddivu\t" } } */
+/* { dg-final { scan-assembler-not "\tmflo\t" } } */
+/* { dg-final { scan-assembler "\tmfhi\t" } } */
+
+typedef unsigned int DI __attribute__((mode(DI)));
+
+MIPS16 DI
+f (DI x, DI y)
+{
+ return x % y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/div-5.c b/gcc/testsuite/gcc.target/mips/div-5.c
new file mode 100644
index 00000000000..a08f3e6f4bd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/div-5.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tdiv\t" } } */
+/* { dg-final { scan-assembler "\tmflo\t" } } */
+/* { dg-final { scan-assembler-not "\tmfhi\t" } } */
+
+typedef int SI __attribute__((mode(SI)));
+
+MIPS16 SI
+f (SI x, SI y)
+{
+ return x / y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/div-6.c b/gcc/testsuite/gcc.target/mips/div-6.c
new file mode 100644
index 00000000000..23075da2c3d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/div-6.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tdivu\t" } } */
+/* { dg-final { scan-assembler "\tmflo\t" } } */
+/* { dg-final { scan-assembler-not "\tmfhi\t" } } */
+
+typedef unsigned int SI __attribute__((mode(SI)));
+
+MIPS16 SI
+f (SI x, SI y)
+{
+ return x / y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/div-7.c b/gcc/testsuite/gcc.target/mips/div-7.c
new file mode 100644
index 00000000000..68f1658484b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/div-7.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tdiv\t" } } */
+/* { dg-final { scan-assembler-not "\tmflo\t" } } */
+/* { dg-final { scan-assembler "\tmfhi\t" } } */
+
+typedef int SI __attribute__((mode(SI)));
+
+MIPS16 SI
+f (SI x, SI y)
+{
+ return x % y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/div-8.c b/gcc/testsuite/gcc.target/mips/div-8.c
new file mode 100644
index 00000000000..c2384b20a9d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/div-8.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tdivu\t" } } */
+/* { dg-final { scan-assembler-not "\tmflo\t" } } */
+/* { dg-final { scan-assembler "\tmfhi\t" } } */
+
+typedef unsigned int SI __attribute__((mode(SI)));
+
+MIPS16 SI
+f (SI x, SI y)
+{
+ return x % y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/div-9.c b/gcc/testsuite/gcc.target/mips/div-9.c
new file mode 100644
index 00000000000..a08f3e6f4bd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/div-9.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tdiv\t" } } */
+/* { dg-final { scan-assembler "\tmflo\t" } } */
+/* { dg-final { scan-assembler-not "\tmfhi\t" } } */
+
+typedef int SI __attribute__((mode(SI)));
+
+MIPS16 SI
+f (SI x, SI y)
+{
+ return x / y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/fix-r4000-1.c b/gcc/testsuite/gcc.target/mips/fix-r4000-1.c
index 513fc6130a5..551d3549d84 100644
--- a/gcc/testsuite/gcc.target/mips/fix-r4000-1.c
+++ b/gcc/testsuite/gcc.target/mips/fix-r4000-1.c
@@ -1,6 +1,6 @@
/* { dg-options "-march=r4000 -mfix-r4000 -O2 -dp" } */
typedef int int32_t;
typedef int uint32_t;
-int32_t foo (int32_t x, int32_t y) { return x * y; }
-uint32_t bar (uint32_t x, uint32_t y) { return x * y; }
+NOMIPS16 int32_t foo (int32_t x, int32_t y) { return x * y; }
+NOMIPS16 uint32_t bar (uint32_t x, uint32_t y) { return x * y; }
/* { dg-final { scan-assembler-times "[concat {\tmult\t\$[45],\$[45][^\n]+mulsi3_r4000[^\n]+\n\tmflo\t\$2\n}]" 2 } } */
diff --git a/gcc/testsuite/gcc.target/mips/fix-r4000-10.c b/gcc/testsuite/gcc.target/mips/fix-r4000-10.c
index ebf3ca30562..8c938b7d219 100644
--- a/gcc/testsuite/gcc.target/mips/fix-r4000-10.c
+++ b/gcc/testsuite/gcc.target/mips/fix-r4000-10.c
@@ -4,5 +4,5 @@
/* { dg-options "-mips3 -mfix-r4000 -mgp64 -O2 -fno-split-wide-types -dp -EL" } */
typedef unsigned long long uint64_t;
typedef unsigned int uint128_t __attribute__((mode(TI)));
-uint128_t foo (uint64_t x, uint64_t y) { return (uint128_t) x * y; }
+NOMIPS16 uint128_t foo (uint64_t x, uint64_t y) { return (uint128_t) x * y; }
/* { dg-final { scan-assembler "[concat {\tdmultu\t\$[45],\$[45][^\n]+umulditi3_r4000[^\n]+\n\tmflo\t\$2\n\tmfhi\t\$3\n}]" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fix-r4000-11.c b/gcc/testsuite/gcc.target/mips/fix-r4000-11.c
index 93f78134e4e..7cfad3d2f79 100644
--- a/gcc/testsuite/gcc.target/mips/fix-r4000-11.c
+++ b/gcc/testsuite/gcc.target/mips/fix-r4000-11.c
@@ -1,4 +1,4 @@
/* { dg-options "-march=r4000 -mfix-r4000 -mgp64 -O2 -dp" } */
typedef long long int64_t;
-int64_t foo (int64_t x) { return x / 11993; }
+NOMIPS16 int64_t foo (int64_t x) { return x / 11993; }
/* { dg-final { scan-assembler "[concat {\tdmult\t\$4,\$[0-9]+[^\n]+smuldi3_highpart[^\n]+\n\tmfhi\t\$[0-9]+\n}]" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fix-r4000-12.c b/gcc/testsuite/gcc.target/mips/fix-r4000-12.c
index 554975ccca1..d449283ddf3 100644
--- a/gcc/testsuite/gcc.target/mips/fix-r4000-12.c
+++ b/gcc/testsuite/gcc.target/mips/fix-r4000-12.c
@@ -1,4 +1,4 @@
/* { dg-options "-march=r4000 -mfix-r4000 -mgp64 -O2 -dp" } */
typedef unsigned long long uint64_t;
-uint64_t foo (uint64_t x) { return x / 11993; }
+NOMIPS16 uint64_t foo (uint64_t x) { return x / 11993; }
/* { dg-final { scan-assembler "[concat {\tdmultu\t\$4,\$[0-9]+[^\n]+umuldi3_highpart[^\n]+\n\tmfhi\t\$[0-9]+\n}]" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fix-r4000-2.c b/gcc/testsuite/gcc.target/mips/fix-r4000-2.c
index 4f27041bedb..6cb7d3594e0 100644
--- a/gcc/testsuite/gcc.target/mips/fix-r4000-2.c
+++ b/gcc/testsuite/gcc.target/mips/fix-r4000-2.c
@@ -1,7 +1,7 @@
/* { dg-options "-mips1 -mfix-r4000 -O2 -dp -EB" } */
typedef int int32_t;
typedef long long int64_t;
-int32_t foo (int32_t x, int32_t y) { return ((int64_t) x * y) >> 32; }
+NOMIPS16 int32_t foo (int32_t x, int32_t y) { return ((int64_t) x * y) >> 32; }
/* ??? A highpart pattern would be a better choice, but we currently
don't use them. */
/* { dg-final { scan-assembler "[concat {\tmult\t\$[45],\$[45][^\n]+mulsidi3_32bit_r4000[^\n]+\n\tmflo\t\$3\n\tmfhi\t\$2\n}]" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fix-r4000-3.c b/gcc/testsuite/gcc.target/mips/fix-r4000-3.c
index 207fc66b062..bd12509d1bd 100644
--- a/gcc/testsuite/gcc.target/mips/fix-r4000-3.c
+++ b/gcc/testsuite/gcc.target/mips/fix-r4000-3.c
@@ -1,7 +1,7 @@
/* { dg-options "-mips1 -mfix-r4000 -O2 -dp -EB" } */
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
-uint32_t foo (uint32_t x, uint32_t y) { return ((uint64_t) x * y) >> 32; }
+NOMIPS16 uint32_t foo (uint32_t x, uint32_t y) { return ((uint64_t) x * y) >> 32; }
/* ??? A highpart pattern would be a better choice, but we currently
don't use them. */
/* { dg-final { scan-assembler "[concat {\tmultu\t\$[45],\$[45][^\n]+umulsidi3_32bit_r4000[^\n]+\n\tmflo\t\$3\n\tmfhi\t\$2\n}]" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fix-r4000-4.c b/gcc/testsuite/gcc.target/mips/fix-r4000-4.c
index be32b57ae4f..3854db8967d 100644
--- a/gcc/testsuite/gcc.target/mips/fix-r4000-4.c
+++ b/gcc/testsuite/gcc.target/mips/fix-r4000-4.c
@@ -4,5 +4,5 @@
/* { dg-options "-mips1 -mfix-r4000 -O2 -fno-split-wide-types -dp -EL" } */
typedef int int32_t;
typedef long long int64_t;
-int64_t foo (int32_t x, int32_t y) { return (int64_t) x * y; }
+NOMIPS16 int64_t foo (int32_t x, int32_t y) { return (int64_t) x * y; }
/* { dg-final { scan-assembler "[concat {\tmult\t\$[45],\$[45][^\n]+mulsidi3_32bit_r4000[^\n]+\n\tmflo\t\$2\n\tmfhi\t\$3\n}]" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fix-r4000-5.c b/gcc/testsuite/gcc.target/mips/fix-r4000-5.c
index c14e949f229..c46300f62db 100644
--- a/gcc/testsuite/gcc.target/mips/fix-r4000-5.c
+++ b/gcc/testsuite/gcc.target/mips/fix-r4000-5.c
@@ -4,5 +4,5 @@
/* { dg-options "-mips1 -mfix-r4000 -O2 -fno-split-wide-types -dp -EL" } */
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
-uint64_t foo (uint32_t x, uint32_t y) { return (uint64_t) x * y; }
+NOMIPS16 uint64_t foo (uint32_t x, uint32_t y) { return (uint64_t) x * y; }
/* { dg-final { scan-assembler "[concat {\tmultu\t\$[45],\$[45][^\n]+umulsidi3_32bit_r4000[^\n]+\n\tmflo\t\$2\n\tmfhi\t\$3\n}]" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fix-r4000-6.c b/gcc/testsuite/gcc.target/mips/fix-r4000-6.c
index 32861f9750b..1e33cc4f765 100644
--- a/gcc/testsuite/gcc.target/mips/fix-r4000-6.c
+++ b/gcc/testsuite/gcc.target/mips/fix-r4000-6.c
@@ -1,6 +1,6 @@
/* { dg-options "-march=r4000 -mfix-r4000 -mgp64 -O2 -dp" } */
typedef long long int64_t;
typedef unsigned long long uint64_t;
-int64_t foo (int64_t x, int64_t y) { return x * y; }
-uint64_t bar (uint64_t x, uint64_t y) { return x * y; }
+NOMIPS16 int64_t foo (int64_t x, int64_t y) { return x * y; }
+NOMIPS16 uint64_t bar (uint64_t x, uint64_t y) { return x * y; }
/* { dg-final { scan-assembler-times "[concat {\tdmult\t\$[45],\$[45][^\n]+muldi3_r4000[^\n]+\n\tmflo\t\$2\n}]" 2 } } */
diff --git a/gcc/testsuite/gcc.target/mips/fix-r4000-7.c b/gcc/testsuite/gcc.target/mips/fix-r4000-7.c
index 2555d5306d7..118ba99dfeb 100644
--- a/gcc/testsuite/gcc.target/mips/fix-r4000-7.c
+++ b/gcc/testsuite/gcc.target/mips/fix-r4000-7.c
@@ -1,7 +1,7 @@
/* { dg-options "-march=r4000 -mfix-r4000 -O2 -mgp64 -dp -EB" } */
typedef long long int64_t;
typedef int int128_t __attribute__((mode(TI)));
-int64_t foo (int64_t x, int64_t y) { return ((int128_t) x * y) >> 64; }
+NOMIPS16 int64_t foo (int64_t x, int64_t y) { return ((int128_t) x * y) >> 64; }
/* ??? A highpart pattern would be a better choice, but we currently
don't use them. */
/* { dg-final { scan-assembler "[concat {\tdmult\t\$[45],\$[45][^\n]+mulditi3[^\n]+\n\tmflo\t\$3\n\tmfhi\t\$2\n}]" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fix-r4000-8.c b/gcc/testsuite/gcc.target/mips/fix-r4000-8.c
index 964dc222291..f2c71c1ef1a 100644
--- a/gcc/testsuite/gcc.target/mips/fix-r4000-8.c
+++ b/gcc/testsuite/gcc.target/mips/fix-r4000-8.c
@@ -1,7 +1,7 @@
/* { dg-options "-march=r4000 -mfix-r4000 -O2 -mgp64 -dp -EB" } */
typedef unsigned long long uint64_t;
typedef unsigned int uint128_t __attribute__((mode(TI)));
-uint64_t foo (uint64_t x, uint64_t y) { return ((uint128_t) x * y) >> 64; }
+NOMIPS16 uint64_t foo (uint64_t x, uint64_t y) { return ((uint128_t) x * y) >> 64; }
/* ??? A highpart pattern would be a better choice, but we currently
don't use them. */
/* { dg-final { scan-assembler "[concat {\tdmultu\t\$[45],\$[45][^\n]+umulditi3[^\n]+\n\tmflo\t\$3\n\tmfhi\t\$2\n}]" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fix-r4000-9.c b/gcc/testsuite/gcc.target/mips/fix-r4000-9.c
index 68724eb376f..da9c11364d2 100644
--- a/gcc/testsuite/gcc.target/mips/fix-r4000-9.c
+++ b/gcc/testsuite/gcc.target/mips/fix-r4000-9.c
@@ -4,5 +4,5 @@
/* { dg-options "-mips3 -mfix-r4000 -mgp64 -O2 -fno-split-wide-types -dp -EL" } */
typedef long long int64_t;
typedef int int128_t __attribute__((mode(TI)));
-int128_t foo (int64_t x, int64_t y) { return (int128_t) x * y; }
+NOMIPS16 int128_t foo (int64_t x, int64_t y) { return (int128_t) x * y; }
/* { dg-final { scan-assembler "[concat {\tdmult\t\$[45],\$[45][^\n]+mulditi3_r4000[^\n]+\n\tmflo\t\$2\n\tmfhi\t\$3\n}]" } } */
diff --git a/gcc/testsuite/gcc.target/mips/mips.exp b/gcc/testsuite/gcc.target/mips/mips.exp
index 9d666fbaca3..55b26f9602d 100644
--- a/gcc/testsuite/gcc.target/mips/mips.exp
+++ b/gcc/testsuite/gcc.target/mips/mips.exp
@@ -834,6 +834,10 @@ proc mips-dg-finish {} {
# | |
# -mexplicit-relocs -mno-explicit-relocs
# | |
+# -mdspr2 -mno-dspr2
+# | |
+# -mdsp -mno-dsp
+# | |
# +-- gp, abi & arch ---------+
#
# For these purposes, the "gp", "abi" & "arch" option groups are treated
@@ -1136,7 +1140,6 @@ proc mips-dg-options { args } {
mips_make_test_option options "-mfp32"
}
mips_make_test_option options "-mno-dsp"
- mips_make_test_option options "-mno-dspr2"
}
unset arch
unset isa
@@ -1144,6 +1147,7 @@ proc mips-dg-options { args } {
}
# Handle dependencies between options on the right of the diagram.
+ mips_option_dependency options "-mno-dsp" "-mno-dspr2"
mips_option_dependency options "-mno-explicit-relocs" "-mgpopt"
switch -- [mips_test_option options small-data] {
"" -
diff --git a/gcc/testsuite/gcc.target/mips/mult-10.c b/gcc/testsuite/gcc.target/mips/mult-10.c
new file mode 100644
index 00000000000..0b990c36413
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mult-10.c
@@ -0,0 +1,13 @@
+/* { dg-options "-O2 -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tmult\t" } } */
+/* { dg-final { scan-assembler-not "\tmflo\t" { xfail *-*-* } } } */
+/* { dg-final { scan-assembler "\tmfhi\t" } } */
+
+typedef int DI __attribute__((mode(DI)));
+typedef int SI __attribute__((mode(SI)));
+
+MIPS16 SI
+f (SI x, SI y)
+{
+ return ((DI) x * y) >> 32;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mult-11.c b/gcc/testsuite/gcc.target/mips/mult-11.c
new file mode 100644
index 00000000000..d2ba695f6dd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mult-11.c
@@ -0,0 +1,13 @@
+/* { dg-options "-O2 -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tmultu\t" } } */
+/* { dg-final { scan-assembler-not "\tmflo\t" } } */
+/* { dg-final { scan-assembler "\tmfhi\t" } } */
+
+typedef unsigned int DI __attribute__((mode(DI)));
+typedef unsigned int SI __attribute__((mode(SI)));
+
+MIPS16 SI
+f (SI x, SI y)
+{
+ return ((DI) x * y) >> 32;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mult-12.c b/gcc/testsuite/gcc.target/mips/mult-12.c
new file mode 100644
index 00000000000..bd772d2cd74
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mult-12.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tmultu?\t" } } */
+/* { dg-final { scan-assembler "\tmflo\t" } } */
+/* { dg-final { scan-assembler-not "\tmfhi\t" } } */
+
+typedef int SI __attribute__((mode(SI)));
+
+MIPS16 SI
+f (SI x, SI y)
+{
+ return x * y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mult-13.c b/gcc/testsuite/gcc.target/mips/mult-13.c
new file mode 100644
index 00000000000..e0859f629f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mult-13.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tmultu?\t" } } */
+/* { dg-final { scan-assembler "\tmflo\t" } } */
+/* { dg-final { scan-assembler-not "\tmfhi\t" } } */
+
+typedef unsigned int SI __attribute__((mode(SI)));
+
+MIPS16 SI
+f (SI x, SI y)
+{
+ return x * y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mult-14.c b/gcc/testsuite/gcc.target/mips/mult-14.c
new file mode 100644
index 00000000000..c4b54b7ec45
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mult-14.c
@@ -0,0 +1,15 @@
+/* { dg-options "-O -mgp32 (-mips16)" } */
+/* { dg-final { scan-assembler "\tmult\t" } } */
+/* { dg-final { scan-assembler "\tmflo\t" } } */
+/* { dg-final { scan-assembler "\tmfhi\t" } } */
+/* { dg-final { scan-assembler-not "\tdsll\t" } } */
+/* { dg-final { scan-assembler-not "\tdsrl\t" } } */
+
+typedef int DI __attribute__((mode(DI)));
+typedef int SI __attribute__((mode(SI)));
+
+MIPS16 DI
+f (SI x, SI y)
+{
+ return (DI) x * y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mult-15.c b/gcc/testsuite/gcc.target/mips/mult-15.c
new file mode 100644
index 00000000000..a96049e04e6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mult-15.c
@@ -0,0 +1,15 @@
+/* { dg-options "-O -mgp32 (-mips16)" } */
+/* { dg-final { scan-assembler "\tmultu\t" } } */
+/* { dg-final { scan-assembler "\tmflo\t" } } */
+/* { dg-final { scan-assembler "\tmfhi\t" } } */
+/* { dg-final { scan-assembler-not "\tdsll\t" } } */
+/* { dg-final { scan-assembler-not "\tdsrl\t" } } */
+
+typedef unsigned int DI __attribute__((mode(DI)));
+typedef unsigned int SI __attribute__((mode(SI)));
+
+MIPS16 DI
+f (SI x, SI y)
+{
+ return (DI) x * y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mult-16.c b/gcc/testsuite/gcc.target/mips/mult-16.c
new file mode 100644
index 00000000000..cb1707d9125
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mult-16.c
@@ -0,0 +1,13 @@
+/* { dg-options "-O2 -mgp32 (-mips16)" } */
+/* { dg-final { scan-assembler "\tmult\t" } } */
+/* { dg-final { scan-assembler-not "\tmflo\t" } } */
+/* { dg-final { scan-assembler "\tmfhi\t" } } */
+
+typedef int DI __attribute__((mode(DI)));
+typedef int SI __attribute__((mode(SI)));
+
+MIPS16 SI
+f (SI x, SI y)
+{
+ return ((DI) x * y) >> 32;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mult-17.c b/gcc/testsuite/gcc.target/mips/mult-17.c
new file mode 100644
index 00000000000..3539f63d96a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mult-17.c
@@ -0,0 +1,13 @@
+/* { dg-options "-O -mgp32 (-mips16)" } */
+/* { dg-final { scan-assembler "\tmultu\t" } } */
+/* { dg-final { scan-assembler-not "\tmflo\t" } } */
+/* { dg-final { scan-assembler "\tmfhi\t" } } */
+
+typedef unsigned int DI __attribute__((mode(DI)));
+typedef unsigned int SI __attribute__((mode(SI)));
+
+MIPS16 SI
+f (SI x, SI y)
+{
+ return ((DI) x * y) >> 32;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mult-18.c b/gcc/testsuite/gcc.target/mips/mult-18.c
new file mode 100644
index 00000000000..cfdac8b0de1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mult-18.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O -mgp32 (-mips16)" } */
+/* { dg-final { scan-assembler "\tmultu?\t" } } */
+/* { dg-final { scan-assembler "\tmflo\t" } } */
+/* { dg-final { scan-assembler-not "\tmfhi\t" } } */
+
+typedef int SI __attribute__((mode(SI)));
+
+MIPS16 SI
+f (SI x, SI y)
+{
+ return x * y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mult-19.c b/gcc/testsuite/gcc.target/mips/mult-19.c
new file mode 100644
index 00000000000..47cdd5c23c3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mult-19.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O -mgp32 (-mips16)" } */
+/* { dg-final { scan-assembler "\tmultu?\t" } } */
+/* { dg-final { scan-assembler "\tmflo\t" } } */
+/* { dg-final { scan-assembler-not "\tmfhi\t" } } */
+
+typedef unsigned int SI __attribute__((mode(SI)));
+
+MIPS16 SI
+f (SI x, SI y)
+{
+ return x * y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mult-2.c b/gcc/testsuite/gcc.target/mips/mult-2.c
new file mode 100644
index 00000000000..8494e14c358
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mult-2.c
@@ -0,0 +1,13 @@
+/* { dg-options "-O -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tdmult\t" } } */
+/* { dg-final { scan-assembler "\tmfhi\t" } } */
+/* { dg-final { scan-assembler "\tmflo\t" } } */
+
+typedef int TI __attribute__((mode(TI)));
+typedef int DI __attribute__((mode(DI)));
+
+MIPS16 TI
+f (DI x, DI y)
+{
+ return (TI) x * y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mult-3.c b/gcc/testsuite/gcc.target/mips/mult-3.c
new file mode 100644
index 00000000000..fa7cfa34e23
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mult-3.c
@@ -0,0 +1,13 @@
+/* { dg-options "-O -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tdmultu\t" } } */
+/* { dg-final { scan-assembler "\tmfhi\t" } } */
+/* { dg-final { scan-assembler "\tmflo\t" } } */
+
+typedef unsigned int TI __attribute__((mode(TI)));
+typedef unsigned int DI __attribute__((mode(DI)));
+
+MIPS16 TI
+f (DI x, DI y)
+{
+ return (TI) x * y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mult-4.c b/gcc/testsuite/gcc.target/mips/mult-4.c
new file mode 100644
index 00000000000..d579f0023d2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mult-4.c
@@ -0,0 +1,13 @@
+/* { dg-options "-O2 -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tdmult\t" } } */
+/* { dg-final { scan-assembler "\tmfhi\t" } } */
+/* { dg-final { scan-assembler-not "\tmflo\t" } } */
+
+typedef int TI __attribute__((mode(TI)));
+typedef int DI __attribute__((mode(DI)));
+
+MIPS16 DI
+f (DI x, DI y)
+{
+ return ((TI) x * y) >> 64;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mult-5.c b/gcc/testsuite/gcc.target/mips/mult-5.c
new file mode 100644
index 00000000000..6df86a1163d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mult-5.c
@@ -0,0 +1,13 @@
+/* { dg-options "-O -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tdmultu\t" } } */
+/* { dg-final { scan-assembler "\tmfhi\t" } } */
+/* { dg-final { scan-assembler-not "\tmflo\t" } } */
+
+typedef unsigned int TI __attribute__((mode(TI)));
+typedef unsigned int DI __attribute__((mode(DI)));
+
+MIPS16 DI
+f (DI x, DI y)
+{
+ return ((TI) x * y) >> 64;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mult-6.c b/gcc/testsuite/gcc.target/mips/mult-6.c
new file mode 100644
index 00000000000..a6b910ec402
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mult-6.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tdmultu?\t" } } */
+/* { dg-final { scan-assembler "\tmflo\t" } } */
+/* { dg-final { scan-assembler-not "\tmfhi\t" } } */
+
+typedef int DI __attribute__((mode(DI)));
+
+MIPS16 DI
+f (DI x, DI y)
+{
+ return x * y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mult-7.c b/gcc/testsuite/gcc.target/mips/mult-7.c
new file mode 100644
index 00000000000..7c2989baa52
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mult-7.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tdmultu?\t" } } */
+/* { dg-final { scan-assembler "\tmflo\t" } } */
+/* { dg-final { scan-assembler-not "\tmfhi\t" } } */
+
+typedef unsigned int DI __attribute__((mode(DI)));
+
+MIPS16 DI
+f (DI x, DI y)
+{
+ return x * y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mult-8.c b/gcc/testsuite/gcc.target/mips/mult-8.c
new file mode 100644
index 00000000000..3e3acde81e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mult-8.c
@@ -0,0 +1,15 @@
+/* { dg-options "-O2 -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tmult\t" } } */
+/* { dg-final { scan-assembler "\tmflo\t" } } */
+/* { dg-final { scan-assembler "\tmfhi\t" } } */
+/* { dg-final { scan-assembler-times "\tdsll\t" 2 } } */
+/* { dg-final { scan-assembler "\tdsrl\t" } } */
+
+typedef int DI __attribute__((mode(DI)));
+typedef int SI __attribute__((mode(SI)));
+
+MIPS16 DI
+f (SI x, SI y)
+{
+ return (DI) x * y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mult-9.c b/gcc/testsuite/gcc.target/mips/mult-9.c
new file mode 100644
index 00000000000..aa2ededa67a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mult-9.c
@@ -0,0 +1,15 @@
+/* { dg-options "-O2 -mgp64 (-mips16)" } */
+/* { dg-final { scan-assembler "\tmultu\t" } } */
+/* { dg-final { scan-assembler "\tmflo\t" } } */
+/* { dg-final { scan-assembler "\tmfhi\t" } } */
+/* { dg-final { scan-assembler-times "\tdsll\t" 2 } } */
+/* { dg-final { scan-assembler "\tdsrl\t" } } */
+
+typedef unsigned int DI __attribute__((mode(DI)));
+typedef unsigned int SI __attribute__((mode(SI)));
+
+MIPS16 DI
+f (SI x, SI y)
+{
+ return (DI) x * y;
+}
diff --git a/gcc/testsuite/gcc.target/mips/no-dsp-1.c b/gcc/testsuite/gcc.target/mips/no-dsp-1.c
new file mode 100644
index 00000000000..093037579b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/no-dsp-1.c
@@ -0,0 +1,7 @@
+/* { dg-options "-mno-dsp" } */
+
+void
+foo (void)
+{
+ register int x asm ("$ac1hi"); /* { dg-error "cannot be accessed" } */
+}
diff --git a/gcc/testsuite/gcc.target/mips/soft-float-1.c b/gcc/testsuite/gcc.target/mips/soft-float-1.c
new file mode 100644
index 00000000000..4c456462797
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/soft-float-1.c
@@ -0,0 +1,7 @@
+/* { dg-options "-msoft-float" } */
+
+void
+foo (void)
+{
+ register float x asm ("$f0"); /* { dg-error "cannot be accessed" } */
+}
diff --git a/gcc/testsuite/gfortran.dg/c_ptr_tests_17.f90 b/gcc/testsuite/gfortran.dg/c_ptr_tests_17.f90
new file mode 100644
index 00000000000..9bbd0dd41ad
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c_ptr_tests_17.f90
@@ -0,0 +1,88 @@
+! { dg-do compile }
+!
+! PR fortran/37829
+!
+! Contributed by James Van Buskirk and Jerry DeLisle.
+!
+! Fix derived-type loading with ISO_BIND_C's C_PTR/C_FUNPTR.
+
+module m3
+ use ISO_C_BINDING
+ implicit none
+ private
+
+ public kill_C_PTR
+ interface
+ function kill_C_PTR() bind(C)
+ import
+ implicit none
+ type(C_PTR) kill_C_PTR
+ end function kill_C_PTR
+ end interface
+
+ public kill_C_FUNPTR
+ interface
+ function kill_C_FUNPTR() bind(C)
+ import
+ implicit none
+ type(C_FUNPTR) kill_C_FUNPTR
+ end function kill_C_FUNPTR
+ end interface
+end module m3
+
+module m1
+ use m3
+end module m1
+
+program X
+ use m1
+ use ISO_C_BINDING
+ implicit none
+ type(C_PTR) cp
+ type(C_FUNPTR) fp
+ integer(C_INT),target :: i
+ interface
+ function fun() bind(C)
+ use ISO_C_BINDING
+ implicit none
+ real(C_FLOAT) fun
+ end function fun
+ end interface
+
+ cp = C_NULL_PTR
+ cp = C_LOC(i)
+ fp = C_NULL_FUNPTR
+ fp = C_FUNLOC(fun)
+end program X
+
+function fun() bind(C)
+ use ISO_C_BINDING
+ implicit none
+ real(C_FLOAT) fun
+ fun = 1.0
+end function fun
+
+function kill_C_PTR() bind(C)
+ use ISO_C_BINDING
+ implicit none
+ type(C_PTR) kill_C_PTR
+ integer(C_INT), pointer :: p
+ allocate(p)
+ kill_C_PTR = C_LOC(p)
+end function kill_C_PTR
+
+function kill_C_FUNPTR() bind(C)
+ use ISO_C_BINDING
+ implicit none
+ type(C_FUNPTR) kill_C_FUNPTR
+ interface
+ function fun() bind(C)
+ use ISO_C_BINDING
+ implicit none
+ real(C_FLOAT) fun
+ end function fun
+ end interface
+ kill_C_FUNPTR = C_FUNLOC(fun)
+end function kill_C_FUNPTR
+
+! { dg-final { cleanup-modules "m3 m1" } }
diff --git a/gcc/testsuite/gfortran.dg/c_ptr_tests_18.f90 b/gcc/testsuite/gfortran.dg/c_ptr_tests_18.f90
new file mode 100644
index 00000000000..6239516ec2e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c_ptr_tests_18.f90
@@ -0,0 +1,35 @@
+! { dg-do compile }
+!
+! PR fortran/37829
+! PR fortran/45190
+!
+! Contributed by Mat Cross
+!
+! Fix derived-type loading with ISO_BIND_C's C_PTR/C_FUNPTR.
+
+MODULE NAG_J_TYPES
+ USE ISO_C_BINDING, ONLY : C_PTR
+ IMPLICIT NONE
+ TYPE :: NAG_IMAGE
+ INTEGER :: WIDTH, HEIGHT, PXFMT, NCHAN
+ TYPE (C_PTR) :: PIXELS
+ END TYPE NAG_IMAGE
+END MODULE NAG_J_TYPES
+program cfpointerstress
+ use nag_j_types
+ use iso_c_binding
+ implicit none
+ type(nag_image),pointer :: img
+ type(C_PTR) :: ptr
+ real, pointer :: r
+ allocate(r)
+ allocate(img)
+ r = 12
+ ptr = c_loc(img)
+ write(*,*) 'C_ASSOCIATED =', C_ASSOCIATED(ptr)
+ call c_f_pointer(ptr, img)
+ write(*,*) 'ASSOCIATED =', associated(img)
+ deallocate(r)
+end program cfpointerstress
+
+! { dg-final { cleanup-modules "nag_j_types" } }
diff --git a/gcc/testsuite/gfortran.dg/constructor_1.f90 b/gcc/testsuite/gfortran.dg/constructor_1.f90
new file mode 100644
index 00000000000..e8fe03ac38c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/constructor_1.f90
@@ -0,0 +1,42 @@
+! { dg-do compile }
+!
+! PR fortran/39427
+!
+! Check constructor functionality.
+!
+! Contributed by Damian Rouson.
+!
+module mycomplex_module
+ private
+ public :: mycomplex
+ type mycomplex
+! private
+ real :: argument, modulus
+ end type
+ interface mycomplex
+ module procedure complex_to_mycomplex, two_reals_to_mycomplex
+ end interface
+! :
+ contains
+ type(mycomplex) function complex_to_mycomplex(c)
+ complex, intent(in) :: c
+! :
+ end function complex_to_mycomplex
+ type(mycomplex) function two_reals_to_mycomplex(x,y)
+ real, intent(in) :: x
+ real, intent(in), optional :: y
+! :
+ end function two_reals_to_mycomplex
+! :
+ end module mycomplex_module
+! :
+program myuse
+ use mycomplex_module
+ type(mycomplex) :: a, b, c
+! :
+ a = mycomplex(argument=5.6, modulus=1.0) ! The structure constructor
+ c = mycomplex(x=0.0, y=1.0) ! A function reference
+ c = mycomplex(0.0, 1.0) ! A function reference
+end program myuse
+
+! { dg-final { cleanup-modules "mycomplex_module" } }
diff --git a/gcc/testsuite/gfortran.dg/constructor_2.f90 b/gcc/testsuite/gfortran.dg/constructor_2.f90
new file mode 100644
index 00000000000..0e3d8af29f3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/constructor_2.f90
@@ -0,0 +1,73 @@
+! { dg-do run }
+!
+! PR fortran/39427
+!
+module foo_module
+ interface foo
+ procedure constructor
+ end interface
+
+ type foo
+ integer :: bar
+ end type
+contains
+ type(foo) function constructor()
+ constructor%bar = 1
+ end function
+
+ subroutine test_foo()
+ type(foo) :: f
+ f = foo()
+ if (f%bar /= 1) call abort ()
+ f = foo(2)
+ if (f%bar /= 2) call abort ()
+ end subroutine test_foo
+end module foo_module
+
+
+! Same as foo_module but order
+! of INTERFACE and TYPE reversed
+module bar_module
+ type bar
+ integer :: bar
+ end type
+
+ interface bar
+ procedure constructor
+ end interface
+contains
+ type(bar) function constructor()
+ constructor%bar = 3
+ end function
+
+ subroutine test_bar()
+ type(bar) :: f
+ f = bar()
+ if (f%bar /= 3) call abort ()
+ f = bar(4)
+ if (f%bar /= 4) call abort ()
+ end subroutine test_bar
+end module bar_module
+
+program main
+ use foo_module
+ use bar_module
+ implicit none
+
+ type(foo) :: f
+ type(bar) :: b
+
+ call test_foo()
+ f = foo()
+ if (f%bar /= 1) call abort ()
+ f = foo(2)
+ if (f%bar /= 2) call abort ()
+
+ call test_bar()
+ b = bar()
+ if (b%bar /= 3) call abort ()
+ b = bar(4)
+ if (b%bar /= 4) call abort ()
+end program main
+
+! { dg-final { cleanup-tree-dump "foo_module bar_module" } }
diff --git a/gcc/testsuite/gfortran.dg/constructor_3.f90 b/gcc/testsuite/gfortran.dg/constructor_3.f90
new file mode 100644
index 00000000000..4015090bced
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/constructor_3.f90
@@ -0,0 +1,47 @@
+! { dg-do run }
+!
+! PR fortran/39427
+!
+! Check constructor functionality.
+!
+!
+module m
+ interface cons
+ procedure cons42
+ end interface cons
+contains
+ integer function cons42()
+ cons42 = 42
+ end function cons42
+end module m
+
+
+module m2
+ type cons
+ integer :: j = -1
+ end type cons
+ interface cons
+ procedure consT
+ end interface cons
+contains
+ type(cons) function consT(k)
+ integer :: k
+ consT%j = k**2
+ end function consT
+end module m2
+
+
+use m
+use m2, only: cons
+implicit none
+type(cons) :: x
+integer :: k
+x = cons(3)
+k = cons()
+if (x%j /= 9) call abort ()
+if (k /= 42) call abort ()
+!print *, x%j
+!print *, k
+end
+
+! { dg-final { cleanup-modules "m m2" } }
diff --git a/gcc/testsuite/gfortran.dg/constructor_4.f90 b/gcc/testsuite/gfortran.dg/constructor_4.f90
new file mode 100644
index 00000000000..34dfba80c27
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/constructor_4.f90
@@ -0,0 +1,33 @@
+! { dg-do compile }
+! { dg-options "-std=f95" }
+!
+! PR fortran/39427
+!
+! Check constructor functionality.
+!
+!
+module m
+ type t ! { dg-error "the same name as derived type" }
+ integer :: x
+ end type t
+ interface t
+ module procedure f
+ end interface t
+contains
+ function f() ! { dg-error "the same name as derived type" }
+ type(t) :: f
+ end function
+end module
+
+module m2
+ interface t2
+ module procedure f2
+ end interface t2
+ type t2 ! { dg-error "the same name as derived type" }
+ integer :: x2
+ end type t2
+contains
+ function f2() ! { dg-error "the same name as derived type" }
+ type(t2) :: f2
+ end function
+end module
diff --git a/gcc/testsuite/gfortran.dg/constructor_5.f90 b/gcc/testsuite/gfortran.dg/constructor_5.f90
new file mode 100644
index 00000000000..ab9c9f2f5e3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/constructor_5.f90
@@ -0,0 +1,34 @@
+! { dg-do compile }
+!
+! PR fortran/39427
+!
+! Check constructor functionality.
+!
+!
+module m
+ type t
+ integer :: x
+ end type t
+ interface t
+ module procedure f
+ end interface t
+contains
+ function f()
+ type(t) :: f
+ end function
+end module
+
+module m2
+ interface t2
+ module procedure f2
+ end interface t2
+ type t2
+ integer :: x2
+ end type t2
+contains
+ function f2()
+ type(t2) :: f2
+ end function
+end module
+
+! { dg-final { cleanup-modules "m m2" } }
diff --git a/gcc/testsuite/gfortran.dg/constructor_6.f90 b/gcc/testsuite/gfortran.dg/constructor_6.f90
new file mode 100644
index 00000000000..00b99f2eba6
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/constructor_6.f90
@@ -0,0 +1,171 @@
+! { dg-do run }
+!
+! PR fortran/39427
+!
+! Contributed by Norman S. Clerman (in PR fortran/45155)
+!
+! Constructor test case
+!
+!
+module test_cnt
+ integer, public, save :: my_test_cnt = 0
+end module test_cnt
+
+module Rational
+ use test_cnt
+ implicit none
+ private
+
+ type, public :: rational_t
+ integer :: n = 0, id = 1
+ contains
+ procedure, nopass :: Construct_rational_t
+ procedure :: Print_rational_t
+ procedure, private :: Rational_t_init
+ generic :: Rational_t => Construct_rational_t
+ generic :: print => Print_rational_t
+ end type rational_t
+
+contains
+
+ function Construct_rational_t (message_) result (return_type)
+ character (*), intent (in) :: message_
+ type (rational_t) :: return_type
+
+! print *, trim (message_)
+ if (my_test_cnt /= 1) call abort()
+ my_test_cnt = my_test_cnt + 1
+ call return_type % Rational_t_init
+
+ end function Construct_rational_t
+
+ subroutine Print_rational_t (this_)
+ class (rational_t), intent (in) :: this_
+
+! print *, "n, id", this_% n, this_% id
+ if (my_test_cnt == 0) then
+ if (this_% n /= 0 .or. this_% id /= 1) call abort ()
+ else if (my_test_cnt == 2) then
+ if (this_% n /= 10 .or. this_% id /= 0) call abort ()
+ else
+ call abort ()
+ end if
+ my_test_cnt = my_test_cnt + 1
+ end subroutine Print_rational_t
+
+ subroutine Rational_t_init (this_)
+ class (rational_t), intent (in out) :: this_
+
+ this_% n = 10
+ this_% id = 0
+
+ end subroutine Rational_t_init
+
+end module Rational
+
+module Temp_node
+ use test_cnt
+ implicit none
+ private
+
+ real, parameter :: NOMINAL_TEMP = 20.0
+
+ type, public :: temp_node_t
+ real :: temperature = NOMINAL_TEMP
+ integer :: id = 1
+ contains
+ procedure :: Print_temp_node_t
+ procedure, private :: Temp_node_t_init
+ generic :: Print => Print_temp_node_t
+ end type temp_node_t
+
+ interface temp_node_t
+ module procedure Construct_temp_node_t
+ end interface
+
+contains
+
+ function Construct_temp_node_t (message_) result (return_type)
+ character (*), intent (in) :: message_
+ type (temp_node_t) :: return_type
+
+ !print *, trim (message_)
+ if (my_test_cnt /= 4) call abort()
+ my_test_cnt = my_test_cnt + 1
+ call return_type % Temp_node_t_init
+
+ end function Construct_temp_node_t
+
+ subroutine Print_temp_node_t (this_)
+ class (temp_node_t), intent (in) :: this_
+
+! print *, "temp, id", this_% temperature, this_% id
+ if (my_test_cnt == 3) then
+ if (this_% temperature /= 20 .or. this_% id /= 1) call abort ()
+ else if (my_test_cnt == 5) then
+ if (this_% temperature /= 10 .or. this_% id /= 0) call abort ()
+ else
+ call abort ()
+ end if
+ my_test_cnt = my_test_cnt + 1
+ end subroutine Print_temp_node_t
+
+ subroutine Temp_node_t_init (this_)
+ class (temp_node_t), intent (in out) :: this_
+
+ this_% temperature = 10.0
+ this_% id = 0
+
+ end subroutine Temp_node_t_init
+
+end module Temp_node
+
+program Struct_over
+ use test_cnt
+ use Rational, only : rational_t
+ use Temp_node, only : temp_node_t
+
+ implicit none
+
+ type (rational_t) :: sample_rational_t
+ type (temp_node_t) :: sample_temp_node_t
+
+! print *, "rational_t"
+! print *, "----------"
+! print *, ""
+!
+! print *, "after declaration"
+ if (my_test_cnt /= 0) call abort()
+ call sample_rational_t % print
+
+ if (my_test_cnt /= 1) call abort()
+
+ sample_rational_t = sample_rational_t % rational_t ("using override")
+ if (my_test_cnt /= 2) call abort()
+! print *, "after override"
+ ! call print (sample_rational_t)
+ ! call sample_rational_t % print ()
+ call sample_rational_t % print
+
+ if (my_test_cnt /= 3) call abort()
+
+! print *, "sample_t"
+! print *, "--------"
+! print *, ""
+!
+! print *, "after declaration"
+ call sample_temp_node_t % print
+
+ if (my_test_cnt /= 4) call abort()
+
+ sample_temp_node_t = temp_node_t ("using override")
+ if (my_test_cnt /= 5) call abort()
+! print *, "after override"
+ ! call print (sample_rational_t)
+ ! call sample_rational_t % print ()
+ call sample_temp_node_t % print
+ if (my_test_cnt /= 6) call abort()
+
+end program Struct_over
+
+! { dg-final { cleanup-modules "test_cnt rational temp_node" } }
diff --git a/gcc/testsuite/gfortran.dg/function_types_3.f90 b/gcc/testsuite/gfortran.dg/function_types_3.f90
index 8d00f5f7f1e..49d5d5f561b 100644
--- a/gcc/testsuite/gfortran.dg/function_types_3.f90
+++ b/gcc/testsuite/gfortran.dg/function_types_3.f90
@@ -14,6 +14,6 @@ end
! PR 50403: SIGSEGV in gfc_use_derived
-type(f) function f() ! { dg-error "conflicts with DERIVED attribute|is not accessible" }
+type(f) function f() ! { dg-error "Type name 'f' at .1. conflicts with previously declared entity|The type for function 'f' at .1. is not accessible" }
f=110 ! { dg-error "Unclassifiable statement" }
end
diff --git a/gcc/testsuite/gfortran.dg/implicit_pure_1.f90 b/gcc/testsuite/gfortran.dg/implicit_pure_1.f90
new file mode 100644
index 00000000000..d4a5a364e59
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/implicit_pure_1.f90
@@ -0,0 +1,53 @@
+! { dg-do run }
+!
+! PR fortran/51218
+!
+! Contributed by Harald Anlauf
+!
+
+module a
+ implicit none
+ integer :: neval = 0
+contains
+ subroutine inc_eval
+ neval = neval + 1
+ end subroutine inc_eval
+end module a
+
+module b
+ use a
+ implicit none
+contains
+ function f(x) ! Should be implicit pure
+ real :: f
+ real, intent(in) :: x
+ f = x
+ end function f
+
+ function g(x) ! Should NOT be implicit pure
+ real :: g
+ real, intent(in) :: x
+ call inc_eval
+ g = x
+ end function g
+end module b
+
+program gfcbug114a
+ use a
+ use b
+ implicit none
+ real :: x = 1, y = 1, t, u, v, w
+ if (neval /= 0) call abort ()
+ t = f(x)*f(y)
+ if (neval /= 0) call abort ()
+ u = f(x)*f(y) + f(x)*f(y)
+ if (neval /= 0) call abort ()
+ v = g(x)*g(y)
+ if (neval /= 2) call abort ()
+ w = g(x)*g(y) + g(x)*g(y)
+ if (neval /= 6) call abort ()
+ if (t /= 1.0 .or. u /= 2.0 .or. v /= 1.0 .or. w /= 2) call abort ()
+end program gfcbug114a
+
+! { dg-final { scan-module "b" "IMPLICIT_PURE" } }
+! { dg-final { cleanup-modules "b" } }
diff --git a/gcc/testsuite/gfortran.dg/inline_sum_3.f90 b/gcc/testsuite/gfortran.dg/inline_sum_3.f90
new file mode 100644
index 00000000000..6858228aade
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/inline_sum_3.f90
@@ -0,0 +1,31 @@
+! { dg-do run }
+!
+! PR fortran/51250
+! Wrong loop shape for SUM when arguments are library-allocated arrays.
+!
+! Original testcase provided by Harald Anlauf <anlauf@gmx.de>
+
+program gfcbug115
+ implicit none
+ integer :: n_obstype = 2
+ integer :: nboxes = 1
+ integer :: nprocs = 1
+ integer :: nbox, j
+ integer, allocatable :: nbx(:,:), pes(:)
+
+ allocate (pes(nboxes))
+ allocate (nbx(n_obstype,nboxes))
+ nbx(:,:) = 1
+ do j = 1, nboxes
+ pes(j) = modulo (j-1, nprocs)
+ end do
+ if (any(nbx /= 1)) call abort
+ do j = 0, nprocs-1
+ if (.not. all(spread (pes==j,dim=1,ncopies=n_obstype))) call abort
+ ! The two following tests used to fail
+ if (any(shape(sum(nbx,dim=2,mask=spread (pes==j,dim=1,ncopies=n_obstype))) &
+ /= (/ 2 /))) call abort
+ if (any(sum (nbx,dim=2,mask=spread (pes==j,dim=1,ncopies=n_obstype)) &
+ /= (/ 1, 1 /))) call abort
+ end do
+end program gfcbug115
diff --git a/gcc/testsuite/gfortran.dg/iso_c_binding_compiler_4.f90 b/gcc/testsuite/gfortran.dg/iso_c_binding_compiler_4.f90
new file mode 100644
index 00000000000..8a87fe5f50c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/iso_c_binding_compiler_4.f90
@@ -0,0 +1,18 @@
+! { dg-do compile }
+!
+! PR fortran/51308
+!
+! Contributed by Matthias Moeller
+!
+
+module mymod
+ use iso_c_binding
+ implicit none
+
+ private
+ public :: c_ptr
+ public :: c_null_ptr
+
+end module mymod
+
+! { dg-final { cleanup-modules "mymod" } }
diff --git a/gcc/testsuite/gfortran.dg/result_1.f90 b/gcc/testsuite/gfortran.dg/result_1.f90
index 162ffaf5857..96d2a1febe5 100644
--- a/gcc/testsuite/gfortran.dg/result_1.f90
+++ b/gcc/testsuite/gfortran.dg/result_1.f90
@@ -14,5 +14,10 @@ namelist /s/ a,b,c ! { dg-error "attribute conflicts" }
end function
function h() result(t)
-type t ! { dg-error "attribute conflicts" }
+type t ! { dg-error "GENERIC attribute conflicts with RESULT attribute" }
+end type t ! { dg-error "Expecting END FUNCTION statement" }
+end function
+
+function i() result(t)
+type t ! { dg-error "GENERIC attribute conflicts with RESULT attribute" }
end function
diff --git a/gcc/testsuite/gfortran.dg/structure_constructor_3.f03 b/gcc/testsuite/gfortran.dg/structure_constructor_3.f03
index aa5934951c4..5fb7d612d0e 100644
--- a/gcc/testsuite/gfortran.dg/structure_constructor_3.f03
+++ b/gcc/testsuite/gfortran.dg/structure_constructor_3.f03
@@ -13,6 +13,6 @@ PROGRAM test
TYPE(basics_t) :: basics
- basics = basics_t (i=42, 1.5) ! { dg-error "without name after" }
+ basics = basics_t (i=42, 1.5) ! { dg-error "Missing keyword name" }
END PROGRAM test
diff --git a/gcc/testsuite/gfortran.dg/structure_constructor_4.f03 b/gcc/testsuite/gfortran.dg/structure_constructor_4.f03
index 647be5fbb7d..8a5aaa7a23f 100644
--- a/gcc/testsuite/gfortran.dg/structure_constructor_4.f03
+++ b/gcc/testsuite/gfortran.dg/structure_constructor_4.f03
@@ -14,6 +14,6 @@ PROGRAM test
TYPE(basics_t) :: basics
basics = basics_t (42, r=1.5, i=15) ! { dg-error "'i' is initialized twice" }
- basics = basics_t (42, r=1., r=-2.) ! { dg-error "'r' is initialized twice" }
+ basics = basics_t (42, r=1., r=-2.) ! { dg-error "has already appeared in the current argument list" }
END PROGRAM test
diff --git a/gcc/testsuite/gfortran.dg/type_decl_3.f90 b/gcc/testsuite/gfortran.dg/type_decl_3.f90
new file mode 100644
index 00000000000..a3fc54ad326
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/type_decl_3.f90
@@ -0,0 +1,7 @@
+! { dg-do compile }
+!
+! PR fortran/39427
+!
+ subroutine t(x) ! { dg-error "conflicts with previously declared entity" }
+ type(t) :: x ! { dg-error "conflicts with previously declared entity" }
+ end subroutine t
diff --git a/gcc/testsuite/gfortran.dg/use_only_5.f90 b/gcc/testsuite/gfortran.dg/use_only_5.f90
new file mode 100644
index 00000000000..56d33f42750
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/use_only_5.f90
@@ -0,0 +1,38 @@
+! { dg-do compile }
+!
+! PR fortran/39427
+!
+! Test case was failing with the initial version of the
+! constructor patch.
+!
+! Based on the Fortran XML library FoX
+
+module m_common_attrs
+ implicit none
+ private
+
+ type dict_item
+ integer, allocatable :: i(:)
+ end type dict_item
+
+ type dictionary_t
+ private
+ type(dict_item), pointer :: d => null()
+ end type dictionary_t
+
+ public :: dictionary_t
+ public :: get_prefix_by_index
+
+contains
+ pure function get_prefix_by_index(dict) result(prefix)
+ type(dictionary_t), intent(in) :: dict
+ character(len=size(dict%d%i)) :: prefix
+ end function get_prefix_by_index
+end module m_common_attrs
+
+module m_common_namespaces
+ use m_common_attrs, only: dictionary_t
+ use m_common_attrs, only: get_prefix_by_index
+end module m_common_namespaces
+
+! { dg-final { cleanup-modules "m_common_attrs m_common_namespaces" } }
diff --git a/gcc/testsuite/gfortran.dg/used_types_25.f90 b/gcc/testsuite/gfortran.dg/used_types_25.f90
new file mode 100644
index 00000000000..35ac8c75b86
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/used_types_25.f90
@@ -0,0 +1,17 @@
+! { dg-do compile }
+!
+! Created to check this ambiguity when
+! constructors were added. Cf. PR fortran/39427
+
+module m
+ type t
+ end type t
+end module m
+
+use m
+ type t ! { dg-error "Derived type definition of 't' at .1. has already been defined" }
+ end type t ! { dg-error "Expecting END PROGRAM statement" }
+end
+
+! { dg-final { cleanup-modules "m" } }
+
diff --git a/gcc/testsuite/gfortran.dg/used_types_26.f90 b/gcc/testsuite/gfortran.dg/used_types_26.f90
new file mode 100644
index 00000000000..2c0437f63e1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/used_types_26.f90
@@ -0,0 +1,22 @@
+! { dg-do compile }
+!
+! Check for ambiguity.
+!
+! Added as part of the constructor work (PR fortran/39427).
+!
+ module m
+ type t
+ end type t
+ end module m
+
+ module m2
+ type t
+ end type t
+ end module m2
+
+ use m
+ use m2
+ type(t) :: x ! { dg-error "Type name 't' at .1. is ambiguous" }
+ end
+
+! { dg-final { cleanup-modules "m m2" } }
diff --git a/gcc/testsuite/gfortran.dg/volatile13.f90 b/gcc/testsuite/gfortran.dg/volatile13.f90
new file mode 100644
index 00000000000..b9332226085
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/volatile13.f90
@@ -0,0 +1,11 @@
+! { dg-do compile }
+!
+! PR fortran/51302
+!
+! Volatile DO variable - was ICEing before
+!
+integer, volatile :: i
+integer :: n = 1
+do i = 1, n
+end do
+end
diff --git a/gcc/testsuite/gfortran.dg/whole_file_35.f90 b/gcc/testsuite/gfortran.dg/whole_file_35.f90
new file mode 100644
index 00000000000..46a88655145
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/whole_file_35.f90
@@ -0,0 +1,28 @@
+! { dg-do compile }
+!
+! PR fortran/50408
+!
+! Contributed by Vittorio Zecca
+!
+ module m
+ type int
+ integer :: val
+ end type int
+ interface ichar
+ module procedure uch
+ end interface
+ contains
+ function uch (c)
+ character (len=1), intent (in) :: c
+ type (int) :: uch
+ intrinsic ichar
+ uch%val = 127 - ichar (c)
+ end function uch
+ end module m
+
+ program p
+ use m
+ print *,ichar('~') ! must print "1"
+ end program p
+
+! { dg-final { cleanup-modules "m" } }
diff --git a/gcc/testsuite/gnat.dg/discr32.adb b/gcc/testsuite/gnat.dg/discr32.adb
new file mode 100644
index 00000000000..830a6dfd59a
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/discr32.adb
@@ -0,0 +1,21 @@
+-- { dg-do run }
+-- { dg-options "-gnatws" }
+
+with Discr32_Pkg; use Discr32_Pkg;
+
+procedure Discr32 is
+begin
+
+ if R1'Object_Size /= 32 then
+ raise Program_Error;
+ end if;
+
+ if R2'Object_Size /= R'Object_Size then
+ raise Program_Error;
+ end if;
+
+ if R3'Object_Size /= 64 then
+ raise Program_Error;
+ end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/discr32_pkg.ads b/gcc/testsuite/gnat.dg/discr32_pkg.ads
new file mode 100644
index 00000000000..f1761e4b5e5
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/discr32_pkg.ads
@@ -0,0 +1,24 @@
+package Discr32_Pkg is
+
+ type Enum is (One, Two, Three);
+
+ type R (D : Enum) is record
+ case D is
+ when One => B : Boolean;
+ when Two => I : Integer;
+ when Three => F : Float;
+ end case;
+ end record;
+
+ for R use record
+ D at 0 range 0 .. 1;
+ B at 1 range 0 .. 0;
+ I at 4 range 0 .. 31 + 128;
+-- F at 4 range 0 .. 31;
+ end record;
+
+ subtype R1 is R (One);
+ subtype R2 is R (Two);
+ subtype R3 is R (Three);
+
+end Discr32_Pkg;
diff --git a/gcc/testsuite/lib/gcc-simulate-thread.exp b/gcc/testsuite/lib/gcc-simulate-thread.exp
index b2487d2d8c7..9be5da317b9 100644
--- a/gcc/testsuite/lib/gcc-simulate-thread.exp
+++ b/gcc/testsuite/lib/gcc-simulate-thread.exp
@@ -22,11 +22,6 @@
# Call 'fail' if a given test printed "FAIL:", otherwise call 'pass'.
proc simulate-thread { args } {
-
- # ??? Exit immediately if this is alpha*-*-linux* target, single-stepping
- # executable between ldl_l and stl_c insns in gdb breaks LL/SC chaining.
- if { [istarget alpha*-*-linux*] } { return }
-
if { ![isnative] || [is_remote target] } { return }
if { [llength $args] == 1 } {
@@ -50,35 +45,39 @@ proc simulate-thread { args } {
return
}
+ set message "thread simulation test"
+
send_log "Spawning: $gdb_name -nx -nw -quiet -x $cmd_file ./$exec_file\n"
set res [remote_spawn target "$gdb_name -nx -nw -x $cmd_file ./$exec_file"]
if { $res < 0 || $res == "" } {
- unsupported "$testcase"
+ unsupported "$testcase $message"
return
}
set gdb_worked 0
- remote_expect target [timeout_value] {
+
+ # Set timeout to 10 seconds due to huge amount of generated log.
+ remote_expect target 10 {
# Too old GDB
-re "Unhandled dwarf expression|Error in sourced command file" {
- unsupported "$testcase"
+ unsupported "$testcase $message"
remote_close target
return
}
-re "FAIL:" {
- fail "$testcase"
+ fail "$testcase $message"
remote_close target
return
}
- # If the gdb output contained simulate_thread_main, assume
+ # If the gdb output contained simulate_thread_done, assume
# that at the very least, we had a working gdb that was able
- # to break in simulate_thread_main.
- -re "simulate_thread_main" {
+ # to break in simulate_thread_done.
+ -re "simulate_thread_done" {
set gdb_worked 1
exp_continue
}
timeout {
- unsupported "$testcase"
+ fail "$testcase $message"
remote_close target
return
}
@@ -86,10 +85,10 @@ proc simulate-thread { args } {
remote_close target
if {$gdb_worked} {
- pass "$testcase"
+ pass "$testcase $message"
} else {
- # Fail in the absence of a sane GDB.
- fail "$testcase"
+ # Unsupported in the absence of a sane GDB.
+ unsupported "$testcase $message"
}
return
}
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 94309102034..78223afe601 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -2476,7 +2476,7 @@ proc check_effective_target_ultrasparc_hw { } {
# instructions. We check this by attempting: "bmask %g0, %g0, %g0"
proc check_effective_target_ultrasparc_vis2_hw { } {
- return [check_runtime ultrasparc_hw {
+ return [check_runtime ultrasparc_vis2_hw {
int main() { __asm__(".word 0x81b00320"); return 0; }
} "-mcpu=ultrasparc3"]
}
@@ -2485,7 +2485,7 @@ proc check_effective_target_ultrasparc_vis2_hw { } {
# instructions. We check this by attempting: "addxc %g0, %g0, %g0"
proc check_effective_target_ultrasparc_vis3_hw { } {
- return [check_runtime ultrasparc_hw {
+ return [check_runtime ultrasparc_vis3_hw {
int main() { __asm__(".word 0x81b00220"); return 0; }
} "-mcpu=niagara3"]
}
@@ -3620,11 +3620,81 @@ proc check_effective_target_sync_int_128 { } {
}
}
-# Return 1 if the target supports atomic operations on "long long".
+# Return 1 if the target supports atomic operations on "int_128" values
+# and can execute them.
-proc check_effective_target_sync_long_long { } {
+proc check_effective_target_sync_int_128_runtime { } {
if { ([istarget x86_64-*-*] || [istarget i?86-*-*])
&& ![is-effective-target ia32] } {
+ return [check_cached_effective_target sync_int_128_available {
+ check_runtime_nocache sync_int_128_available {
+ #include "cpuid.h"
+ int main ()
+ {
+ unsigned int eax, ebx, ecx, edx;
+ if (__get_cpuid (1, &eax, &ebx, &ecx, &edx))
+ return !(ecx & bit_CMPXCHG16B);
+ return 1;
+ }
+ } ""
+ }]
+ } else {
+ return 0
+ }
+}
+
+# Return 1 if the target supports atomic operations on "long long".
+#
+# Note: 32bit x86 targets require -march=pentium in dg-options.
+
+proc check_effective_target_sync_long_long { } {
+ if { [istarget x86_64-*-*]
+ || [istarget i?86-*-*])
+ || [istarget arm*-*-*]
+ || [istarget alpha*-*-*] } {
+ return 1
+ } else {
+ return 0
+ }
+}
+
+# Return 1 if the target supports atomic operations on "long long"
+# and can execute them.
+#
+# Note: 32bit x86 targets require -march=pentium in dg-options.
+
+proc check_effective_target_sync_long_long_runtime { } {
+ if { [istarget x86_64-*-*]
+ || [istarget i?86-*-*] } {
+ return [check_cached_effective_target sync_long_long_available {
+ check_runtime_nocache sync_long_long_available {
+ #include "cpuid.h"
+ int main ()
+ {
+ unsigned int eax, ebx, ecx, edx;
+ if (__get_cpuid (1, &eax, &ebx, &ecx, &edx))
+ return !(edx & bit_CMPXCHG8B);
+ return 1;
+ }
+ } ""
+ }]
+ } elseif { [istarget arm*-*-linux-gnueabi] } {
+ return [check_runtime sync_longlong_runtime {
+ #include <stdlib.h>
+ int main ()
+ {
+ long long l1;
+
+ if (sizeof (long long) != 8)
+ exit (1);
+
+ /* Just check for native; checking for kernel fallback is tricky. */
+ asm volatile ("ldrexd r0,r1, [%0]" : : "r" (&l1) : "r0", "r1");
+
+ exit (0);
+ }
+ } "" ]
+ } elseif { [istarget alpha*-*-*] } {
return 1
} else {
return 0
@@ -3662,31 +3732,6 @@ 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/toplev.c b/gcc/toplev.c
index de255b4c3f7..9be910970b4 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1333,6 +1333,11 @@ process_options (void)
"and -ftree-loop-linear)");
#endif
+ /* One region RA really helps to decrease the code size. */
+ if (flag_ira_region == IRA_REGION_AUTODETECT)
+ flag_ira_region
+ = optimize_size || !optimize ? IRA_REGION_ONE : IRA_REGION_MIXED;
+
/* Unrolling all loops implies that standard loop unrolling must also
be done. */
if (flag_unroll_all_loops)
diff --git a/gcc/tracer.c b/gcc/tracer.c
index d3523b985b1..602e7580d99 100644
--- a/gcc/tracer.c
+++ b/gcc/tracer.c
@@ -90,10 +90,19 @@ bb_seen_p (basic_block bb)
static bool
ignore_bb_p (const_basic_block bb)
{
+ gimple g;
+
if (bb->index < NUM_FIXED_BLOCKS)
return true;
if (optimize_bb_for_size_p (bb))
return true;
+
+ /* A transaction is a single entry multiple exit region. It must be
+ duplicated in its entirety or not at all. */
+ g = last_stmt (CONST_CAST_BB (bb));
+ if (g && gimple_code (g) == GIMPLE_TRANSACTION)
+ return true;
+
return false;
}
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index 3c0bd600943..751572c4fb4 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -659,13 +659,27 @@ diagnose_tm_1 (gimple_stmt_iterator *gsi, bool *handled_ops_p,
if (TREE_CODE (fn) == ADDR_EXPR)
fn = TREE_OPERAND (fn, 0);
if (d->block_flags & DIAG_TM_SAFE)
- error_at (gimple_location (stmt),
- "unsafe function call %qD within "
- "atomic transaction", fn);
+ {
+ if (direct_call_p)
+ error_at (gimple_location (stmt),
+ "unsafe function call %qD within "
+ "atomic transaction", fn);
+ else
+ error_at (gimple_location (stmt),
+ "unsafe function call %qE within "
+ "atomic transaction", fn);
+ }
else
- error_at (gimple_location (stmt),
- "unsafe function call %qD within "
- "%<transaction_safe%> function", fn);
+ {
+ if (direct_call_p)
+ error_at (gimple_location (stmt),
+ "unsafe function call %qD within "
+ "%<transaction_safe%> function", fn);
+ else
+ error_at (gimple_location (stmt),
+ "unsafe function call %qE within "
+ "%<transaction_safe%> function", fn);
+ }
}
}
}
@@ -2319,7 +2333,8 @@ expand_block_tm (struct tm_region *region, basic_block bb)
{
case GIMPLE_ASSIGN:
/* Only memory reads/writes need to be instrumented. */
- if (gimple_assign_single_p (stmt))
+ if (gimple_assign_single_p (stmt)
+ && !gimple_clobber_p (stmt))
{
expand_assign_tm (region, &gsi);
continue;
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index 89d123d65e9..a0d86ec9c11 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -1385,17 +1385,33 @@ initialize_data_dependence_relation (struct data_reference *a,
return res;
}
- /* When the references are exactly the same, don't spend time doing
- the data dependence tests, just initialize the ddr and return. */
+ /* The case where the references are exactly the same. */
if (operand_equal_p (DR_REF (a), DR_REF (b), 0))
{
+ if (loop_nest
+ && !object_address_invariant_in_loop_p (VEC_index (loop_p, loop_nest, 0),
+ DR_BASE_OBJECT (a)))
+ {
+ DDR_ARE_DEPENDENT (res) = chrec_dont_know;
+ return res;
+ }
DDR_AFFINE_P (res) = true;
DDR_ARE_DEPENDENT (res) = NULL_TREE;
DDR_SUBSCRIPTS (res) = VEC_alloc (subscript_p, heap, DR_NUM_DIMENSIONS (a));
DDR_LOOP_NEST (res) = loop_nest;
DDR_INNER_LOOP (res) = 0;
DDR_SELF_REFERENCE (res) = true;
- compute_self_dependence (res);
+ for (i = 0; i < DR_NUM_DIMENSIONS (a); i++)
+ {
+ struct subscript *subscript;
+
+ subscript = XNEW (struct subscript);
+ SUB_CONFLICTS_IN_A (subscript) = conflict_fn_not_known ();
+ SUB_CONFLICTS_IN_B (subscript) = conflict_fn_not_known ();
+ SUB_LAST_CONFLICT (subscript) = chrec_dont_know;
+ SUB_DISTANCE (subscript) = chrec_dont_know;
+ VEC_safe_push (subscript_p, heap, DDR_SUBSCRIPTS (res), subscript);
+ }
return res;
}
@@ -4040,8 +4056,7 @@ compute_affine_dependence (struct data_dependence_relation *ddr,
}
/* Analyze only when the dependence relation is not yet known. */
- if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE
- && !DDR_SELF_REFERENCE (ddr))
+ if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
{
dependence_stats.num_dependence_tests++;
@@ -4116,39 +4131,6 @@ compute_affine_dependence (struct data_dependence_relation *ddr,
fprintf (dump_file, ")\n");
}
-/* This computes the dependence relation for the same data
- reference into DDR. */
-
-void
-compute_self_dependence (struct data_dependence_relation *ddr)
-{
- unsigned int i;
- struct subscript *subscript;
-
- if (DDR_ARE_DEPENDENT (ddr) != NULL_TREE)
- return;
-
- for (i = 0; VEC_iterate (subscript_p, DDR_SUBSCRIPTS (ddr), i, subscript);
- i++)
- {
- if (SUB_CONFLICTS_IN_A (subscript))
- free_conflict_function (SUB_CONFLICTS_IN_A (subscript));
- if (SUB_CONFLICTS_IN_B (subscript))
- free_conflict_function (SUB_CONFLICTS_IN_B (subscript));
-
- /* The accessed index overlaps for each iteration. */
- SUB_CONFLICTS_IN_A (subscript)
- = conflict_fn (1, affine_fn_cst (integer_zero_node));
- SUB_CONFLICTS_IN_B (subscript)
- = conflict_fn (1, affine_fn_cst (integer_zero_node));
- SUB_LAST_CONFLICT (subscript) = chrec_dont_know;
- }
-
- /* The distance vector is the zero vector. */
- save_dist_v (ddr, lambda_vector_new (DDR_NB_LOOPS (ddr)));
- save_dir_v (ddr, lambda_vector_new (DDR_NB_LOOPS (ddr)));
-}
-
/* Compute in DEPENDENCE_RELATIONS the data dependence graph for all
the data references in DATAREFS, in the LOOP_NEST. When
COMPUTE_SELF_AND_RR is FALSE, don't compute read-read and self
@@ -4179,7 +4161,8 @@ compute_all_dependences (VEC (data_reference_p, heap) *datarefs,
{
ddr = initialize_data_dependence_relation (a, a, loop_nest);
VEC_safe_push (ddr_p, heap, *dependence_relations, ddr);
- compute_self_dependence (ddr);
+ if (loop_nest)
+ compute_affine_dependence (ddr, VEC_index (loop_p, loop_nest, 0));
}
}
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 7daa9d2f513..22604030d4a 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -3521,7 +3521,7 @@ estimate_num_insns (gimple stmt, eni_weights *weights)
case GIMPLE_CALL:
{
tree decl = gimple_call_fndecl (stmt);
- struct cgraph_node *node;
+ struct cgraph_node *node = NULL;
/* Do not special case builtins where we see the body.
This just confuse inliner. */
@@ -3556,7 +3556,7 @@ estimate_num_insns (gimple stmt, eni_weights *weights)
}
}
- cost = weights->call_cost;
+ cost = node ? weights->call_cost : weights->indirect_call_cost;
if (gimple_call_lhs (stmt))
cost += estimate_move_cost (TREE_TYPE (gimple_call_lhs (stmt)));
for (i = 0; i < gimple_call_num_args (stmt); i++)
@@ -3674,6 +3674,7 @@ void
init_inline_once (void)
{
eni_size_weights.call_cost = 1;
+ eni_size_weights.indirect_call_cost = 3;
eni_size_weights.target_builtin_call_cost = 1;
eni_size_weights.div_mod_cost = 1;
eni_size_weights.omp_cost = 40;
@@ -3686,6 +3687,7 @@ init_inline_once (void)
underestimating the cost does less harm than overestimating it, so
we choose a rather small value here. */
eni_time_weights.call_cost = 10;
+ eni_time_weights.indirect_call_cost = 15;
eni_time_weights.target_builtin_call_cost = 1;
eni_time_weights.div_mod_cost = 10;
eni_time_weights.omp_cost = 40;
diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h
index 2aac5f8b9d3..ba0b2c46995 100644
--- a/gcc/tree-inline.h
+++ b/gcc/tree-inline.h
@@ -135,6 +135,9 @@ typedef struct eni_weights_d
/* Cost per call. */
unsigned call_cost;
+ /* Cost per indirect call. */
+ unsigned indirect_call_cost;
+
/* Cost per call to a target specific builtin */
unsigned target_builtin_call_cost;
diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c
index 4de45001e67..45060f70eb0 100644
--- a/gcc/tree-outof-ssa.c
+++ b/gcc/tree-outof-ssa.c
@@ -1021,6 +1021,8 @@ insert_backedge_copies (void)
basic_block bb;
gimple_stmt_iterator gsi;
+ mark_dfs_back_edges ();
+
FOR_EACH_BB (bb)
{
/* Mark block as possibly needing calculation of UIDs. */
diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c
index 2a2c13393fe..b8a056ebdac 100644
--- a/gcc/tree-ssa-live.c
+++ b/gcc/tree-ssa-live.c
@@ -374,7 +374,8 @@ mark_all_vars_used_1 (tree *tp, int *walk_subtrees, void *data)
eliminated as unused. */
if (TREE_CODE (t) == VAR_DECL)
{
- if (data != NULL && bitmap_clear_bit ((bitmap) data, DECL_UID (t)))
+ if (data != NULL && bitmap_clear_bit ((bitmap) data, DECL_UID (t))
+ && DECL_CONTEXT (t) == current_function_decl)
mark_all_vars_used (&DECL_INITIAL (t), data);
set_is_used (t);
}
@@ -836,7 +837,8 @@ remove_unused_locals (void)
if (TREE_CODE (var) == VAR_DECL
&& is_global_var (var)
&& var_ann (var) != NULL
- && is_used_p (var))
+ && is_used_p (var)
+ && DECL_CONTEXT (var) == current_function_decl)
mark_all_vars_used (&DECL_INITIAL (var), global_unused_vars);
num = VEC_length (tree, cfun->local_decls);
diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
index 17e7f374b05..a501b0778a2 100644
--- a/gcc/tree-ssa-tail-merge.c
+++ b/gcc/tree-ssa-tail-merge.c
@@ -742,7 +742,7 @@ delete_worklist (void)
/* Mark BB as deleted, and mark its predecessors. */
static void
-delete_basic_block_same_succ (basic_block bb)
+mark_basic_block_deleted (basic_block bb)
{
edge e;
edge_iterator ei;
@@ -809,15 +809,6 @@ release_last_vdef (basic_block bb)
}
-/* Delete all deleted_bbs. */
-
-static void
-purge_bbs (void)
-{
- bitmap_and_compl_into (deleted_bb_preds, deleted_bbs);
- bitmap_clear (deleted_bbs);
-}
-
/* For deleted_bb_preds, find bbs with same successors. */
static void
@@ -828,6 +819,9 @@ update_worklist (void)
basic_block bb;
same_succ same;
+ bitmap_and_compl_into (deleted_bb_preds, deleted_bbs);
+ bitmap_clear (deleted_bbs);
+
bitmap_clear_bit (deleted_bb_preds, ENTRY_BLOCK);
same_succ_flush_bbs (deleted_bb_preds);
@@ -1353,125 +1347,6 @@ 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 (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, var;
- unsigned int i;
- gimple def_stmt2 = NULL;
- imm_use_iterator iter;
- use_operand_p use_p;
- edge_iterator ei;
- edge e;
-
- if (vuse2 != NULL_TREE)
- {
- var = SSA_NAME_VAR (vuse2);
- def_stmt2 = SSA_NAME_DEF_STMT (vuse2);
- }
- else
- var = SSA_NAME_VAR (vuse1);
-
- if (def_stmt2 && gimple_bb (def_stmt2) == bb2)
- /* Update existing phi. */
- phi = def_stmt2;
- else
- {
- /* No need to create a phi with 2 equal arguments. */
- if (vuse1 == vuse2)
- return;
-
- /* Create a phi. */
- 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, arg, e, UNKNOWN_LOCATION);
- }
-
- /* Update phi. */
- for (i = 0; i < EDGE_COUNT (redirected_edges); ++i)
- {
- e = VEC_index (edge, redirected_edges, i);
- 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 (def_stmt2 && gimple_bb (def_stmt2) == bb2)
- return;
-
- /* 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
- && !dominated_by_p (CDI_DOMINATORS, gimple_bb (stmt), bb2))
- continue;
-
- FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
- {
- if (gimple_code (stmt) == GIMPLE_PHI)
- {
- unsigned int pred_index = PHI_ARG_INDEX_FROM_USE (use_p);
- basic_block pred = EDGE_PRED (gimple_bb (stmt), pred_index)->src;
- 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);
- }
- }
-}
-
/* Returns the vop phi of BB, if any. */
static gimple
@@ -1489,176 +1364,19 @@ vop_phi (basic_block bb)
return NULL;
}
-/* Returns the vop state at the entry of BB, if found in BB or a successor
- bb. */
-
-static tree
-vop_at_entry (basic_block bb)
-{
- gimple bb_phi, succ_phi;
- gimple_stmt_iterator gsi;
- gimple stmt;
- tree vuse, vdef;
- basic_block succ;
-
- bb_phi = vop_phi (bb);
- if (bb_phi != NULL)
- return gimple_phi_result (bb_phi);
-
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- stmt = gsi_stmt (gsi);
- vuse = gimple_vuse (stmt);
- vdef = gimple_vdef (stmt);
- if (vuse != NULL_TREE)
- return vuse;
- if (vdef != NULL_TREE)
- return NULL_TREE;
- }
-
- if (EDGE_COUNT (bb->succs) == 0)
- return NULL_TREE;
-
- succ = EDGE_SUCC (bb, 0)->dest;
- succ_phi = vop_phi (succ);
- return (succ_phi != NULL
- ? PHI_ARG_DEF_FROM_EDGE (succ_phi, find_edge (bb, succ))
- : NULL_TREE);
-}
-
-/* Given that all incoming edges of BB1 have been redirected to BB2, delete BB1
- and recompute dominator info. */
+/* Redirect all edges from BB1 to BB2, removes BB1 and marks it as removed. */
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. */
-
-static void
-replace_block_by (basic_block bb1, basic_block bb2, bool update_vops)
+replace_block_by (basic_block bb1, basic_block bb2)
{
edge pred_edge;
unsigned int i;
- tree phi_vuse1 = NULL_TREE, phi_vuse2 = NULL_TREE, arg;
- 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);
-
- /* 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 (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
- edges. */
- FOR_EACH_EDGE (e, ei, bb1->preds)
- {
- arg = PHI_ARG_DEF_FROM_EDGE (SSA_NAME_DEF_STMT (phi_vuse1), e);
- BB_VOP_AT_EXIT (e->src) = arg;
- }
- vuse1_phi_args = true;
- }
+ gimple bb2_phi;
- /* Mark the basic block for later deletion. */
- delete_basic_block_same_succ (bb1);
+ bb2_phi = vop_phi (bb2);
- if (update_vops)
- redirected_edges = VEC_alloc (edge, heap, 10);
+ /* Mark the basic block as deleted. */
+ mark_basic_block_deleted (bb1);
/* Redirect the incoming edges of bb1 to bb2. */
for (i = EDGE_COUNT (bb1->preds); i > 0 ; --i)
@@ -1666,27 +1384,28 @@ replace_block_by (basic_block bb1, basic_block bb2, bool update_vops)
pred_edge = EDGE_PRED (bb1, i - 1);
pred_edge = redirect_edge_and_branch (pred_edge, bb2);
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);
+
+ if (bb2_phi == NULL)
+ continue;
+
+ /* The phi might have run out of capacity when the redirect added an
+ argument, which means it could have been replaced. Refresh it. */
+ bb2_phi = vop_phi (bb2);
+
+ add_phi_arg (bb2_phi, SSA_NAME_VAR (gimple_phi_result (bb2_phi)),
+ pred_edge, UNKNOWN_LOCATION);
}
+ bb2->frequency += bb1->frequency;
+ if (bb2->frequency > BB_FREQ_MAX)
+ bb2->frequency = BB_FREQ_MAX;
+ bb1->frequency = 0;
+
/* Do updates that use bb1, before deleting bb1. */
- if (!update_vops)
- release_last_vdef (bb1);
+ 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 (vuse1_phi_args, phi_vuse1, phi_vuse2, bb2,
- redirected_edges);
- VEC_free (edge, heap, redirected_edges);
- }
+ delete_basic_block (bb1);
}
/* Bbs for which update_debug_stmt need to be called. */
@@ -1694,10 +1413,10 @@ replace_block_by (basic_block bb1, basic_block bb2, bool update_vops)
static bitmap update_bbs;
/* For each cluster in all_clusters, merge all cluster->bbs. Returns
- number of bbs removed. Insert vop phis if UPDATE_VOPS. */
+ number of bbs removed. */
static int
-apply_clusters (bool update_vops)
+apply_clusters (void)
{
basic_block bb1, bb2;
bb_cluster c;
@@ -1720,7 +1439,7 @@ apply_clusters (bool update_vops)
bb1 = BASIC_BLOCK (j);
bitmap_clear_bit (update_bbs, bb1->index);
- replace_block_by (bb1, bb2, update_vops);
+ replace_block_by (bb1, bb2);
nr_bbs_removed++;
}
}
@@ -1772,9 +1491,6 @@ update_debug_stmts (void)
bitmap_iterator bi;
unsigned int i;
- if (!MAY_HAVE_DEBUG_STMTS)
- return;
-
EXECUTE_IF_SET_IN_BITMAP (update_bbs, 0, i, bi)
{
gimple stmt;
@@ -1800,7 +1516,6 @@ tail_merge_optimize (unsigned int todo)
int nr_bbs_removed;
bool loop_entered = false;
int iteration_nr = 0;
- bool update_vops = !symbol_marked_for_renaming (gimple_vop (cfun));
int max_iterations = PARAM_VALUE (PARAM_MAX_TAIL_MERGE_ITERATIONS);
if (!flag_tree_tail_merge || max_iterations == 0)
@@ -1831,16 +1546,17 @@ tail_merge_optimize (unsigned int todo)
if (VEC_empty (bb_cluster, all_clusters))
break;
- nr_bbs_removed = apply_clusters (update_vops);
+ nr_bbs_removed = apply_clusters ();
nr_bbs_removed_total += nr_bbs_removed;
if (nr_bbs_removed == 0)
break;
- purge_bbs ();
+ free_dominance_info (CDI_DOMINATORS);
if (iteration_nr == max_iterations)
break;
+ calculate_dominance_info (CDI_DOMINATORS);
update_worklist ();
}
@@ -1850,7 +1566,11 @@ tail_merge_optimize (unsigned int todo)
if (nr_bbs_removed_total > 0)
{
- update_debug_stmts ();
+ if (MAY_HAVE_DEBUG_STMTS)
+ {
+ calculate_dominance_info (CDI_DOMINATORS);
+ update_debug_stmts ();
+ }
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -1860,6 +1580,7 @@ tail_merge_optimize (unsigned int todo)
todo |= (TODO_verify_ssa | TODO_verify_stmts | TODO_verify_flow
| TODO_dump_func);
+ mark_sym_for_renaming (gimple_vop (cfun));
}
delete_worklist ();
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 0ff8ee83d40..8111bdc61ac 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -3122,7 +3122,6 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo,
ddr = VEC_index (ddr_p, ddrs, k);
gcc_assert (DDR_A (ddr) == olddr && DDR_B (ddr) == olddr);
newddr = initialize_data_dependence_relation (dr, dr, nest);
- compute_self_dependence (newddr);
VEC_replace (ddr_p, ddrs, k, newddr);
free_dependence_relation (ddr);
VEC_replace (data_reference_p, datarefs, i, dr);
diff --git a/gcc/tree.c b/gcc/tree.c
index ba6c2e1ef8a..72603b59945 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -6994,7 +6994,6 @@ iterative_hash_expr (const_tree t, hashval_t val)
val = iterative_hash_expr (TREE_OPERAND (t, i), val);
}
return val;
- break;
}
}
diff --git a/gcc/tree.def b/gcc/tree.def
index 2a2363e7037..11ce8b5b756 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -900,8 +900,7 @@ DEFTREECODE (CATCH_EXPR, "catch_expr", tcc_statement, 2)
/* Used to represent an exception specification. EH_FILTER_TYPES is a list
of allowed types, and EH_FILTER_FAILURE is an expression to evaluate on
- failure. EH_FILTER_MUST_NOT_THROW controls which range type to use when
- expanding. */
+ failure. */
DEFTREECODE (EH_FILTER_EXPR, "eh_filter_expr", tcc_statement, 2)
/* Node used for describing a property that is known at compile
diff --git a/gcc/tree.h b/gcc/tree.h
index a76b0bc891a..fa4adac5d80 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5460,7 +5460,6 @@ extern tree build_va_arg_indirect_ref (tree);
extern tree build_string_literal (int, const char *);
extern bool validate_arglist (const_tree, ...);
extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
-extern bool is_builtin_name (const char *);
extern bool is_builtin_fn (tree);
extern unsigned int get_object_alignment_1 (tree, unsigned HOST_WIDE_INT *);
extern unsigned int get_object_alignment (tree);
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index 95bc02b183c..4e07d25b54a 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -3008,7 +3008,7 @@ loc_cmp (rtx x, rtx y)
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));
+ return loc_cmp (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y));
}
if (GET_CODE (y) == ENTRY_VALUE)
diff --git a/gcc/varasm.c b/gcc/varasm.c
index cfbb9ca1f2e..8d555487818 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -1198,16 +1198,23 @@ make_decl_rtl (tree decl)
else if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
{
const char *asmspec = name+1;
+ enum machine_mode mode = DECL_MODE (decl);
reg_number = decode_reg_name (asmspec);
/* First detect errors in declaring global registers. */
if (reg_number == -1)
error ("register name not specified for %q+D", decl);
else if (reg_number < 0)
error ("invalid register name for %q+D", decl);
- else if (TYPE_MODE (TREE_TYPE (decl)) == BLKmode)
+ else if (mode == BLKmode)
error ("data type of %q+D isn%'t suitable for a register",
decl);
- else if (! HARD_REGNO_MODE_OK (reg_number, TYPE_MODE (TREE_TYPE (decl))))
+ else if (!in_hard_reg_set_p (accessible_reg_set, mode, reg_number))
+ error ("the register specified for %q+D cannot be accessed"
+ " by the current target", decl);
+ else if (!in_hard_reg_set_p (operand_reg_set, mode, reg_number))
+ error ("the register specified for %q+D is not general enough"
+ " to be used as a register variable", decl);
+ else if (!HARD_REGNO_MODE_OK (reg_number, mode))
error ("register specified for %q+D isn%'t suitable for data type",
decl);
/* Now handle properly declared static register variables. */
@@ -1230,7 +1237,7 @@ make_decl_rtl (tree decl)
confused with that register and be eliminated. This usage is
somewhat suspect... */
- SET_DECL_RTL (decl, gen_rtx_raw_REG (DECL_MODE (decl), reg_number));
+ SET_DECL_RTL (decl, gen_rtx_raw_REG (mode, reg_number));
ORIGINAL_REGNO (DECL_RTL (decl)) = reg_number;
REG_USERVAR_P (DECL_RTL (decl)) = 1;
@@ -1242,7 +1249,7 @@ make_decl_rtl (tree decl)
name = IDENTIFIER_POINTER (DECL_NAME (decl));
ASM_DECLARE_REGISTER_GLOBAL (asm_out_file, decl, reg_number, name);
#endif
- nregs = hard_regno_nregs[reg_number][DECL_MODE (decl)];
+ nregs = hard_regno_nregs[reg_number][mode];
while (nregs > 0)
globalize_reg (decl, reg_number + --nregs);
}
@@ -2109,7 +2116,9 @@ incorporeal_function_p (tree decl)
return true;
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- if (is_builtin_name (name))
+ /* Atomic or sync builtins which have survived this far will be
+ resolved externally and therefore are not incorporeal. */
+ if (strncmp (name, "__builtin_", 10) == 0)
return true;
}
return false;
@@ -5961,7 +5970,7 @@ dump_tm_clone_pairs (VEC(tm_alias_pair,heap) *tm_alias_pairs)
if (!switched)
{
- switch_to_section (get_named_section (NULL, ".tm_clone_table", 3));
+ switch_to_section (targetm.asm_out.tm_clone_table_section ());
assemble_align (POINTER_SIZE);
switched = true;
}
@@ -5973,6 +5982,14 @@ dump_tm_clone_pairs (VEC(tm_alias_pair,heap) *tm_alias_pairs)
}
}
+/* Provide a default for the tm_clone_table section. */
+
+section *
+default_clone_table_section (void)
+{
+ return get_named_section (NULL, ".tm_clone_table", 3);
+}
+
/* Helper comparison function for qsorting by the DECL_UID stored in
alias_pair->emitted_diags. */
diff --git a/libada/ChangeLog b/libada/ChangeLog
index 921b1bd7789..17269228d3e 100644
--- a/libada/ChangeLog
+++ b/libada/ChangeLog
@@ -1,6 +1,6 @@
2011-11-12 Iain Sandoe <iains@gcc.gnu.org>
- Makefile.in: Change dependency on oscons to depend on the generator
+ * Makefile.in: Change dependency on oscons to depend on the generator
tool.
2011-10-12 Eric Botcazou <ebotcazou@adacore.com>
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 8f7d494fc91..1df9e080268 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,15 @@
+2011-11-22 Diego Novillo <dnovillo@google.com>
+
+ * include/line-map.h (linemap_dump): Declare.
+ (line_table_dump): Declare.
+ * line-map.c (linemap_dump): New.
+ (line_table_dump): New.
+
+2011-11-21 Ed Smith-Rowland <3dw4rd@verizon.net>
+
+ PR c++/50958
+ * expr.c (cpp_userdef_char_remove_type): Fix typo.
+
2011-11-03 Michael Matz <matz@suse.de>
PR bootstrap/50857
diff --git a/libcpp/expr.c b/libcpp/expr.c
index 7bbc72d6f26..d56e56a6311 100644
--- a/libcpp/expr.c
+++ b/libcpp/expr.c
@@ -284,9 +284,9 @@ cpp_userdef_char_remove_type (enum cpp_ttype type)
else if (type == CPP_WCHAR_USERDEF)
return CPP_WCHAR;
else if (type == CPP_CHAR16_USERDEF)
- return CPP_STRING16;
+ return CPP_CHAR16;
else if (type == CPP_CHAR32_USERDEF)
- return CPP_STRING32;
+ return CPP_CHAR32;
else
return type;
}
diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h
index 112bc020309..4e30742596c 100644
--- a/libcpp/include/line-map.h
+++ b/libcpp/include/line-map.h
@@ -705,4 +705,14 @@ void linemap_get_statistics (struct line_maps *, struct linemap_stats *);
stream STREAM. SET is the line map set LOC comes from. */
void linemap_dump_location (struct line_maps *, source_location, FILE *);
+/* Dump line map at index IX in line table SET to STREAM. If STREAM
+ is NULL, use stderr. IS_MACRO is true if the caller wants to
+ dump a macro map, false otherwise. */
+void linemap_dump (FILE *, struct line_maps *, unsigned, bool);
+
+/* Dump line table SET to STREAM. If STREAM is NULL, stderr is used.
+ NUM_ORDINARY specifies how many ordinary maps to dump. NUM_MACRO
+ specifies how many macro maps to dump. */
+void line_table_dump (FILE *, struct line_maps *, unsigned int, unsigned int);
+
#endif /* !LIBCPP_LINE_MAP_H */
diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index 23a0347cb5f..d7752bb4e61 100644
--- a/libcpp/line-map.c
+++ b/libcpp/line-map.c
@@ -1153,6 +1153,57 @@ linemap_expand_location (struct line_maps *set,
return xloc;
}
+
+/* Dump line map at index IX in line table SET to STREAM. If STREAM
+ is NULL, use stderr. IS_MACRO is true if the caller wants to
+ dump a macro map, false otherwise. */
+
+void
+linemap_dump (FILE *stream, struct line_maps *set, unsigned ix, bool is_macro)
+{
+ const char *lc_reasons_v[LC_ENTER_MACRO + 1]
+ = { "LC_ENTER", "LC_LEAVE", "LC_RENAME", "LC_RENAME_VERBATIM",
+ "LC_ENTER_MACRO" };
+ const char *reason;
+ struct line_map *map;
+
+ if (stream == NULL)
+ stream = stderr;
+
+ if (!is_macro)
+ map = LINEMAPS_ORDINARY_MAP_AT (set, ix);
+ else
+ map = LINEMAPS_MACRO_MAP_AT (set, ix);
+
+ reason = (map->reason <= LC_ENTER_MACRO) ? lc_reasons_v[map->reason] : "???";
+
+ fprintf (stream, "Map #%u [%p] - LOC: %u - REASON: %s - SYSP: %s\n",
+ ix, (void *) map, map->start_location, reason,
+ (!is_macro && ORDINARY_MAP_IN_SYSTEM_HEADER_P (map)) ? "yes" : "no");
+ if (!is_macro)
+ {
+ unsigned includer_ix;
+ struct line_map *includer_map;
+
+ includer_ix = ORDINARY_MAP_INCLUDER_FILE_INDEX (map);
+ includer_map = includer_ix < LINEMAPS_ORDINARY_USED (set)
+ ? LINEMAPS_ORDINARY_MAP_AT (set, includer_ix)
+ : NULL;
+
+ fprintf (stream, "File: %s:%d\n", ORDINARY_MAP_FILE_NAME (map),
+ ORDINARY_MAP_STARTING_LINE_NUMBER (map));
+ fprintf (stream, "Included from: [%d] %s\n", includer_ix,
+ includer_map ? ORDINARY_MAP_FILE_NAME (includer_map) : "None");
+ }
+ else
+ fprintf (stream, "Macro: %s (%u tokens)\n",
+ linemap_map_get_macro_name (map),
+ MACRO_MAP_NUM_MACRO_TOKENS (map));
+
+ fprintf (stream, "\n");
+}
+
+
/* Dump debugging information about source location LOC into the file
stream STREAM. SET is the line map set LOC comes from. */
@@ -1254,3 +1305,42 @@ linemap_get_statistics (struct line_maps *set,
s->duplicated_macro_maps_locations_size =
duplicated_macro_maps_locations_size;
}
+
+
+/* Dump line table SET to STREAM. If STREAM is NULL, stderr is used.
+ NUM_ORDINARY specifies how many ordinary maps to dump. NUM_MACRO
+ specifies how many macro maps to dump. */
+
+void
+line_table_dump (FILE *stream, struct line_maps *set, unsigned int num_ordinary,
+ unsigned int num_macro)
+{
+ unsigned int i;
+
+ if (set == NULL)
+ return;
+
+ if (stream == NULL)
+ stream = stderr;
+
+ fprintf (stream, "# of ordinary maps: %d\n", LINEMAPS_ORDINARY_USED (set));
+ fprintf (stream, "# of macro maps: %d\n", LINEMAPS_MACRO_USED (set));
+ fprintf (stream, "Include stack depth: %d\n", set->depth);
+ fprintf (stream, "Highest location: %u\n", set->highest_location);
+
+ if (num_ordinary)
+ {
+ fprintf (stream, "\nOrdinary line maps\n");
+ for (i = 0; i < num_ordinary && i < LINEMAPS_ORDINARY_USED (set); i++)
+ linemap_dump (stream, set, i, false);
+ fprintf (stream, "\n");
+ }
+
+ if (num_macro)
+ {
+ fprintf (stream, "\nMacro line maps\n");
+ for (i = 0; i < num_macro && i < LINEMAPS_MACRO_USED (set); i++)
+ linemap_dump (stream, set, i, true);
+ fprintf (stream, "\n");
+ }
+}
diff --git a/libffi/ChangeLog b/libffi/ChangeLog
index 2c34801a354..113a1617cbe 100644
--- a/libffi/ChangeLog
+++ b/libffi/ChangeLog
@@ -1,3 +1,7 @@
+2011-11-21 Andreas Tobler <andreast@fgznet.ch>
+
+ * configure: Regenerate.
+
2011-11-10 Richard Henderson <rth@redhat.com>
* configure.ac (GCC_AS_CFI_PSEUDO_OP): Use it instead of inline check.
diff --git a/libffi/configure b/libffi/configure
index 57ccc55f4ad..3abd665a6f7 100755
--- a/libffi/configure
+++ b/libffi/configure
@@ -9001,7 +9001,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct=yes
hardcode_minus_L=yes
@@ -9914,7 +9914,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -9932,7 +9932,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index c10667bd428..f146181da9c 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,142 @@
+2011-11-28 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ PR other/51022
+ * config/rs6000/t-savresfgpr: New file.
+ * config/rs6000/t-ppccomm (LIB2ADD_ST): Remove all but
+ $(srcdir)/config/rs6000/eabi.S.
+ * config/rs6000/t-ppccomm-ldbl: Remove.
+ * config.host (powerpc-*-freebsd*): Add rs6000/t-savresfgpr to
+ tmake_file.
+ (powerpc-*-eabispe*): Likewise.
+ (powerpc-*-eabi*): Likewise.
+ (powerpc-*-linux*, powerpc64-*-linux*): Likewise.
+ (powerpc-wrs-vxworks, powerpc-wrs-vxworksae): Add rs6000/t-ppccomm
+ to tmake_file, remove rs6000/t-ppccomm-ldbl.
+ (powerpc-*-eabisimaltivec*): Remove rs6000/t-ppccomm-ldbl from
+ tmake_file.
+ (powerpc-*-eabisim*): Likewise.
+ (powerpc-*-elf*): Likewise.
+ (powerpc-*-eabialtivec*): Likewise.
+ (powerpc-xilinx-eabi*): Likewise.
+ (powerpc-*-rtems*): Likewise.
+ (powerpcle-*-elf*): Likewise.
+ (powerpcle-*-eabisim*): Likewise.
+ (powerpcle-*-eabi*): Likewise.
+
+2011-11-27 Ian Lance Taylor <iant@google.com>
+
+ * generic-morestack.c (__splitstack_find): Check for NULL old
+ stack value.
+ (__splitstack_resetcontext): New function.
+ (__splitstack_releasecontext): New function.
+ * libgcc-std.ver.in: Add new functions to GCC_4.7.0.
+
+2011-11-27 Iain Sandoe <iains@gcc.gnu.org>
+
+ * config/darwin-crt-tm.c: Correct comments, use correct licence.
+
+2011-11-27 Iain Sandoe <iains@gcc.gnu.org>
+
+ * config/darwin-crt-tm.c: Remove dummy _ITM_ functions.
+
+2011-11-26 Richard Henderson <rth@redhat.com>
+
+ * config/m68k/linux-atomic.c: New file.
+ * config/m68k/t-linux: New file.
+ * config.host (m68k-uclinux, m68k-linux): Use it.
+
+2011-11-26 Richard Henderson <rth@redhat.com>
+
+ * crtstuff.c (__TMC_LIST__): Mark used not unused.
+ (__TMC_END__): Only declare if hidden is available; in the definition,
+ if hidden is unavailable add a null record.
+ (deregister_tm_clones, register_tm_clones): New.
+ (__do_global_dtors_aux, frame_dummy): Use them.
+ (__do_global_dtors, __do_global_ctors_1): Likewise.
+
+2011-11-22 Iain Sandoe <iains@gcc.gnu.org>
+
+ * config/darwin-crt-tm.c: New file.
+ * config.host (darwin): Build crttms.o crttme.o to provide
+ startup and shutdown for tm clones.
+ * config/t-darwin (crttms.o): New build rule.
+ (crttme.o): Likewise.
+
+2011-11-21 Hans-Peter Nilsson <hp@axis.com>
+
+ * Makefile.in ($(srcdir)/emutls.c): Explain why it's in LIB2ADDEH
+ et al.
+
+2011-11-21 Richard Henderson <rth@redhat.com>
+
+ * crtstuff.c (USE_TM_CLONE_REGISTRY): Default to 1 on ELF.
+ (__TMC_LIST__, __TMC_END__): New.
+ (__do_global_dtors_aux): Call _ITM_deregisterTMCloneTable.
+ (__do_global_dtors): Likewise.
+ (frame_dummy): Call _ITM_registerTMCloneTable.
+ (__do_global_ctors_1): Likewise.
+
+2011-11-21 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * config.host (iq2000*-*-elf*): Add iq2000/t-iq2000 to tmake_file.
+ (powerpc-*-netbsd*): Add rs6000/t-netbsd to tmake_file.
+ (powerpc-wrs-vxworks, powerpc-wrs-vxworksae): Add to tmake_file.
+ (powerpc-*-lynxos*): Add rs6000/t-lynx to tmake_file.
+ * config/i386/t-darwin64: Remove.
+ * config/sh/t-netbsd (LIB2ADD): Remove.
+
+2011-11-21 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/49313
+ * config/avr/t-avr (LIB2FUNCS_EXCLUDE): Add _moddi3, _umoddi3.
+ (LIB1ASMFUNCS): Add _divdi3, _udivdi3, _udivmod64, _negdi2.
+ * config/avr/lib1funcs.S (wmov): New assembler macro.
+ (__umoddi3, __udivdi3, __udivdi3_umoddi3): New functions.
+ (__moddi3, __divdi3, __divdi3_moddi3): New functions.
+ (__udivmod64): New function.
+ (__negdi2): New function.
+
+2011-11-21 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * config.host (*-*-freebsd[12], *-*-freebsd[12].*,
+ *-*-freebsd*aout*): Remove.
+
+2011-11-20 Hans-Peter Nilsson <hp@axis.com>
+
+ * static-object.mk (c_flags-$o): Save c_flags.
+ ($(base)$(objext)): Use it.
+
+2011-11-18 Steve Ellcey <sje@cup.hp.com>
+
+ * Makefile.in (c_flags): Set to -fno-exceptions to build libunwind.
+
+2011-11-18 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/49868
+ * config/avr/t-avr (LIB1ASMFUNCS): Add _xload_2 _xload_3 _xload_4.
+ * config/avr/lib1funcs.S (__xload_2, __xload_3, __xload_4):
+ New functions.
+
+2011-11-16 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
+
+ * config/arm/lib1funcs.asm (udivsi3): Add support for divide
+ functions.
+ (aeabi_uidivmod): Likewise.
+ (umodsi3): Likewise.
+ (divsi3): Likewise.
+ (aeabi_idivmod): Likewise.
+ (modsi3): Likewise.
+
+2011-11-16 Tristan Gingold <gingold@adacore.com>
+
+ * config/alpha/qrnnd.S: Use specific pseudos for VMS.
+
+2011-11-15 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/49868
+ * config/avr/t-avr (LIB1ASMFUNCS): Add _load_3, _load_4.
+ * config/avr/lib1funcs.S (__load_3, __load_4, __xload_2): New functions.
+
2011-11-13 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
* config.host (hppa*64*-*-hpux11*): Remove pa/t-stublib64 from
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index 3a8509d118c..23b72b92475 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -394,6 +394,9 @@ endif
LIB2ADD += enable-execute-stack.c
+# While emutls.c has nothing to do with EH, it is in LIB2ADDEH*
+# instead of LIB2ADD because that's the way to be sure on some targets
+# (e.g. *-*-darwin*) only one copy of it is linked.
LIB2ADDEH += $(srcdir)/emutls.c
LIB2ADDEHSTATIC += $(srcdir)/emutls.c
LIB2ADDEHSHARED += $(srcdir)/emutls.c
@@ -827,9 +830,10 @@ include $(iterator)
endif
-# Build LIBUNWIND.
+# Build LIBUNWIND. Use -fno-exceptions so that the unwind library does
+# not generate calls to __gcc_personality_v0.
-c_flags := -fexceptions
+c_flags := -fno-exceptions
libunwind-objects += $(addsuffix $(objext),$(basename $(notdir $(LIBUNWIND))))
diff --git a/libgcc/config.host b/libgcc/config.host
index 342d60c6be7..a9fb9ad8d08 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -170,16 +170,7 @@ case ${host} in
*-*-darwin*)
asm_hidden_op=.private_extern
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*)
- # This is the place-holder for the generic a.out configuration
- # of FreeBSD. No actual configuration resides here since
- # there was only ever a bare-bones ix86 configuration for
- # a.out and it exists solely in the machine-specific section.
- # This place-holder must exist to avoid dropping into
- # the generic ELF configuration of FreeBSD (i.e. it must be
- # ordered before that section).
+ extra_parts="crt3.o crttms.o crttme.o"
;;
*-*-freebsd*)
# This is the generic ELF configuration of FreeBSD. Later
@@ -672,7 +663,7 @@ ia64-hp-*vms*)
md_unwind_header=ia64/vms-unwind.h
;;
iq2000*-*-elf*)
- tmake_file=t-fdpbit
+ tmake_file="iq2000/t-iq2000 t-fdpbit"
# Don't use default.
extra_parts=
;;
@@ -710,14 +701,14 @@ m68k*-*-netbsdelf*)
;;
m68k*-*-openbsd*)
;;
-m68k-*-uclinux*) # Motorola m68k/ColdFire running uClinux with uClibc
- tmake_file="$tmake_file m68k/t-floatlib"
+m68k-*-uclinux*) # Motorola m68k/ColdFire running uClinux with uClibc
+ tmake_file="$tmake_file m68k/t-floatlib m68k/t-linux"
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"
+ tmake_file="$tmake_file m68k/t-floatlib m68k/t-linux"
# If not configured with --enable-sjlj-exceptions, bump the
# libgcc version number.
if test x$enable_sjlj_exceptions != xyes; then
@@ -852,65 +843,65 @@ powerpc64-*-darwin*)
extra_parts="$extra_parts crt2.o"
;;
powerpc-*-freebsd*)
- tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-crtstuff rs6000/t-freebsd t-softfp-sfdf t-softfp-excl t-softfp t-slibgcc-libgcc"
+ tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-savresfgpr 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"
+ tmake_file="$tmake_file rs6000/t-netbsd rs6000/t-crtstuff"
;;
powerpc-*-eabispe*)
- tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-crtstuff t-crtstuff-pic"
+ tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-savresfgpr 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="${tmake_file} rs6000/t-ppccomm rs6000/t-ppccomm-ldbl rs6000/t-crtstuff t-crtstuff-pic 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-*-eabisim*)
- tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ppccomm-ldbl rs6000/t-crtstuff t-crtstuff-pic 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-*-elf*)
- tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ppccomm-ldbl rs6000/t-crtstuff t-crtstuff-pic t-fdpbit"
+ tmake_file="${tmake_file} rs6000/t-ppccomm 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="${tmake_file} rs6000/t-ppccomm rs6000/t-ppccomm-ldbl rs6000/t-crtstuff t-crtstuff-pic 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-xilinx-eabi*)
- tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ppccomm-ldbl rs6000/t-crtstuff t-crtstuff-pic 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-*-eabi*)
- tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-crtstuff t-crtstuff-pic t-fdpbit"
+ tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-savresfgpr 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="${tmake_file} rs6000/t-ppccomm rs6000/t-ppccomm-ldbl rs6000/t-crtstuff t-crtstuff-pic t-fdpbit"
+ tmake_file="${tmake_file} rs6000/t-ppccomm 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-crtstuff rs6000/t-linux t-softfp-sfdf t-softfp-excl t-dfprules rs6000/t-ppc64-fp t-softfp t-slibgcc-libgcc"
+ tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-savresfgpr 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"
+ tmake_file="$tmake_file rs6000/t-ppccomm t-fdpbit"
;;
powerpc-*-lynxos*)
- tmake_file="$tmake_file t-fdpbit"
+ tmake_file="$tmake_file rs6000/t-lynx t-fdpbit"
;;
powerpcle-*-elf*)
- tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ppccomm-ldbl rs6000/t-crtstuff t-crtstuff-pic t-fdpbit"
+ tmake_file="${tmake_file} rs6000/t-ppccomm 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="${tmake_file} rs6000/t-ppccomm rs6000/t-ppccomm-ldbl rs6000/t-crtstuff t-crtstuff-pic 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"
;;
powerpcle-*-eabi*)
- tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ppccomm-ldbl rs6000/t-crtstuff t-crtstuff-pic 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"
;;
rs6000-ibm-aix4.[3456789]* | powerpc-ibm-aix4.[3456789]*)
diff --git a/libgcc/config/alpha/qrnnd.S b/libgcc/config/alpha/qrnnd.S
index 51b13bce6ad..794cf65b486 100644
--- a/libgcc/config/alpha/qrnnd.S
+++ b/libgcc/config/alpha/qrnnd.S
@@ -33,9 +33,15 @@
.globl __udiv_qrnnd
.ent __udiv_qrnnd
+#ifdef __VMS__
+__udiv_qrnnd..en:
+ .frame $29,0,$26,0
+ .prologue
+#else
__udiv_qrnnd:
.frame $30,0,$26,0
.prologue 0
+#endif
#define cnt $2
#define tmp $3
@@ -160,4 +166,10 @@ $Odd:
bis $31,n0,$0
ret $31,($26),1
+#ifdef __VMS__
+ .link
+ .align 3
+__udiv_qrnnd:
+ .pdesc __udiv_qrnnd..en,null
+#endif
.end __udiv_qrnnd
diff --git a/libgcc/config/arm/lib1funcs.S b/libgcc/config/arm/lib1funcs.S
index 2e76c01df4b..094d79afad6 100644
--- a/libgcc/config/arm/lib1funcs.S
+++ b/libgcc/config/arm/lib1funcs.S
@@ -951,6 +951,17 @@ LSYM(udivsi3_skip_div0_test):
pop { work }
RET
+#elif defined(__ARM_ARCH_EXT_IDIV__)
+
+ ARM_FUNC_START udivsi3
+ ARM_FUNC_ALIAS aeabi_uidiv udivsi3
+
+ cmp r1, #0
+ beq LSYM(Ldiv0)
+
+ udiv r0, r0, r1
+ RET
+
#else /* ARM version/Thumb-2. */
ARM_FUNC_START udivsi3
@@ -997,6 +1008,14 @@ FUNC_START aeabi_uidivmod
mul r2, r0
sub r1, r1, r2
bx r3
+#elif defined(__ARM_ARCH_EXT_IDIV__)
+ARM_FUNC_START aeabi_uidivmod
+ cmp r1, #0
+ beq LSYM(Ldiv0)
+ mov r2, r0
+ udiv r0, r0, r1
+ mls r1, r0, r1, r2
+ RET
#else
ARM_FUNC_START aeabi_uidivmod
cmp r1, #0
@@ -1014,9 +1033,19 @@ ARM_FUNC_START aeabi_uidivmod
/* ------------------------------------------------------------------------ */
#ifdef L_umodsi3
- FUNC_START umodsi3
+#ifdef __ARM_ARCH_EXT_IDIV__
-#ifdef __thumb__
+ ARM_FUNC_START umodsi3
+
+ cmp r1, #0
+ beq LSYM(Ldiv0)
+ udiv r2, r0, r1
+ mls r0, r1, r2, r0
+ RET
+
+#elif defined(__thumb__)
+
+ FUNC_START umodsi3
cmp divisor, #0
beq LSYM(Ldiv0)
@@ -1035,6 +1064,8 @@ LSYM(Lover10):
#else /* ARM version. */
+ FUNC_START umodsi3
+
subs r2, r1, #1 @ compare divisor with 1
bcc LSYM(Ldiv0)
cmpne r0, r1 @ compare dividend with divisor
@@ -1091,6 +1122,16 @@ LSYM(Lover12):
pop { work }
RET
+#elif defined(__ARM_ARCH_EXT_IDIV__)
+
+ ARM_FUNC_START divsi3
+ ARM_FUNC_ALIAS aeabi_idiv divsi3
+
+ cmp r1, #0
+ beq LSYM(Ldiv0)
+ sdiv r0, r0, r1
+ RET
+
#else /* ARM/Thumb-2 version. */
ARM_FUNC_START divsi3
@@ -1153,6 +1194,14 @@ FUNC_START aeabi_idivmod
mul r2, r0
sub r1, r1, r2
bx r3
+#elif defined(__ARM_ARCH_EXT_IDIV__)
+ARM_FUNC_START aeabi_idivmod
+ cmp r1, #0
+ beq LSYM(Ldiv0)
+ mov r2, r0
+ sdiv r0, r0, r1
+ mls r1, r0, r1, r2
+ RET
#else
ARM_FUNC_START aeabi_idivmod
cmp r1, #0
@@ -1170,9 +1219,20 @@ ARM_FUNC_START aeabi_idivmod
/* ------------------------------------------------------------------------ */
#ifdef L_modsi3
- FUNC_START modsi3
+#if defined(__ARM_ARCH_EXT_IDIV__)
-#ifdef __thumb__
+ ARM_FUNC_START modsi3
+
+ cmp r1, #0
+ beq LSYM(Ldiv0)
+
+ sdiv r2, r0, r1
+ mls r0, r1, r2, r0
+ RET
+
+#elif defined(__thumb__)
+
+ FUNC_START modsi3
mov curbit, #1
cmp divisor, #0
@@ -1204,6 +1264,8 @@ LSYM(Lover12):
#else /* ARM version. */
+ FUNC_START modsi3
+
cmp r1, #0
beq LSYM(Ldiv0)
rsbmi r1, r1, #0 @ loops below use unsigned.
diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S
index f7a8f6335c4..c592c4caa5d 100644
--- a/libgcc/config/avr/lib1funcs.S
+++ b/libgcc/config/avr/lib1funcs.S
@@ -61,6 +61,15 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#endif
.endm
+.macro wmov r_dest, r_src
+#if defined (__AVR_HAVE_MOVW__)
+ movw \r_dest, \r_src
+#else
+ mov \r_dest, \r_src
+ mov \r_dest+1, \r_src+1
+#endif
+.endm
+
#if defined (__AVR_HAVE_JMP_CALL__)
#define XCALL call
#define XJMP jmp
@@ -846,6 +855,352 @@ __divmodsi4_exit:
ENDF __divmodsi4
#endif /* defined (L_divmodsi4) */
+
+/*******************************************************
+ Division 64 / 64
+ Modulo 64 % 64
+*******************************************************/
+
+;; Use Speed-optimized Version on "big" Devices, i.e. Devices with
+;; at least 16k of Program Memory. For smaller Devices, depend
+;; on MOVW.
+
+#if defined (__AVR_HAVE_JMP_CALL__)
+# define SPEED_DIV 8
+#elif defined (__AVR_HAVE_MOVW__)
+# define SPEED_DIV 16
+#else
+# define SPEED_DIV 0
+#endif
+
+;; A[0..7]: In: Dividend;
+;; Out: Quotient (T = 0)
+;; Out: Remainder (T = 1)
+#define A0 18
+#define A1 A0+1
+#define A2 A0+2
+#define A3 A0+3
+#define A4 A0+4
+#define A5 A0+5
+#define A6 A0+6
+#define A7 A0+7
+
+;; B[0..7]: In: Divisor; Out: Clobber
+#define B0 10
+#define B1 B0+1
+#define B2 B0+2
+#define B3 B0+3
+#define B4 B0+4
+#define B5 B0+5
+#define B6 B0+6
+#define B7 B0+7
+
+;; C[0..7]: Expand remainder; Out: Remainder (unused)
+#define C0 8
+#define C1 C0+1
+#define C2 30
+#define C3 C2+1
+#define C4 28
+#define C5 C4+1
+#define C6 26
+#define C7 C6+1
+
+;; Holds Signs during Division Routine
+#define SS __tmp_reg__
+
+;; Bit-Counter in Division Routine
+#define R_cnt __zero_reg__
+
+;; Scratch Register for Negation
+#define NN r31
+
+#if defined (L_udivdi3)
+
+;; R25:R18 = R24:R18 umod R17:R10
+;; Ordinary ABI-Function
+
+DEFUN __umoddi3
+ set
+ rjmp __udivdi3_umoddi3
+ENDF __umoddi3
+
+;; R25:R18 = R24:R18 udiv R17:R10
+;; Ordinary ABI-Function
+
+DEFUN __udivdi3
+ clt
+ENDF __udivdi3
+
+DEFUN __udivdi3_umoddi3
+ push C0
+ push C1
+ push C4
+ push C5
+ XCALL __udivmod64
+ pop C5
+ pop C4
+ pop C1
+ pop C0
+ ret
+ENDF __udivdi3_umoddi3
+#endif /* L_udivdi3 */
+
+#if defined (L_udivmod64)
+
+;; Worker Routine for 64-Bit unsigned Quotient and Remainder Computation
+;; No Registers saved/restored; the Callers will take Care.
+;; Preserves B[] and T-flag
+;; T = 0: Compute Quotient in A[]
+;; T = 1: Compute Remainder in A[] and shift SS one Bit left
+
+DEFUN __udivmod64
+
+ ;; Clear Remainder (C6, C7 will follow)
+ clr C0
+ clr C1
+ wmov C2, C0
+ wmov C4, C0
+ ldi C7, 64
+
+#if SPEED_DIV == 0 || SPEED_DIV == 16
+ ;; Initialize Loop-Counter
+ mov R_cnt, C7
+ wmov C6, C0
+#endif /* SPEED_DIV */
+
+#if SPEED_DIV == 8
+
+ push A7
+ clr C6
+
+1: ;; Compare shifted Devidend against Divisor
+ ;; If -- even after Shifting -- it is smaller...
+ CP A7,B0 $ cpc C0,B1 $ cpc C1,B2 $ cpc C2,B3
+ cpc C3,B4 $ cpc C4,B5 $ cpc C5,B6 $ cpc C6,B7
+ brcc 2f
+
+ ;; ...then we can subtract it. Thus, it is legal to shift left
+ $ mov C6,C5 $ mov C5,C4 $ mov C4,C3
+ mov C3,C2 $ mov C2,C1 $ mov C1,C0 $ mov C0,A7
+ mov A7,A6 $ mov A6,A5 $ mov A5,A4 $ mov A4,A3
+ mov A3,A2 $ mov A2,A1 $ mov A1,A0 $ clr A0
+
+ ;; 8 Bits are done
+ subi C7, 8
+ brne 1b
+
+ ;; Shifted 64 Bits: A7 has traveled to C7
+ pop C7
+ ;; Divisor is greater than Dividend. We have:
+ ;; A[] % B[] = A[]
+ ;; A[] / B[] = 0
+ ;; Thus, we can return immediately
+ rjmp 5f
+
+2: ;; Initialze Bit-Counter with Number of Bits still to be performed
+ mov R_cnt, C7
+
+ ;; Push of A7 is not needed because C7 is still 0
+ pop C7
+ clr C7
+
+#elif SPEED_DIV == 16
+
+ ;; Compare shifted Dividend against Divisor
+ cp A7, B3
+ cpc C0, B4
+ cpc C1, B5
+ cpc C2, B6
+ cpc C3, B7
+ brcc 2f
+
+ ;; Divisor is greater than shifted Dividen: We can shift the Dividend
+ ;; and it is still smaller than the Divisor --> Shift one 32-Bit Chunk
+ wmov C2,A6 $ wmov C0,A4
+ wmov A6,A2 $ wmov A4,A0
+ wmov A2,C6 $ wmov A0,C4
+
+ ;; Set Bit Counter to 32
+ lsr R_cnt
+2:
+#elif SPEED_DIV
+#error SPEED_DIV = ?
+#endif /* SPEED_DIV */
+
+;; The very Division + Remainder Routine
+
+3: ;; Left-shift Dividend...
+ lsl A0 $ rol A1 $ rol A2 $ rol A3
+ rol A4 $ rol A5 $ rol A6 $ rol A7
+
+ ;; ...into Remainder
+ rol C0 $ rol C1 $ rol C2 $ rol C3
+ rol C4 $ rol C5 $ rol C6 $ rol C7
+
+ ;; Compare Remainder and Divisor
+ CP C0,B0 $ cpc C1,B1 $ cpc C2,B2 $ cpc C3,B3
+ cpc C4,B4 $ cpc C5,B5 $ cpc C6,B6 $ cpc C7,B7
+
+ brcs 4f
+
+ ;; Divisor fits into Remainder: Subtract it from Remainder...
+ SUB C0,B0 $ sbc C1,B1 $ sbc C2,B2 $ sbc C3,B3
+ sbc C4,B4 $ sbc C5,B5 $ sbc C6,B6 $ sbc C7,B7
+
+ ;; ...and set according Bit in the upcoming Quotient
+ ;; The Bit will travel to its final Position
+ ori A0, 1
+
+4: ;; This Bit is done
+ dec R_cnt
+ brne 3b
+ ;; __zero_reg__ is 0 again
+
+ ;; T = 0: We are fine with the Quotient in A[]
+ ;; T = 1: Copy Remainder to A[]
+5: brtc 6f
+ wmov A0, C0
+ wmov A2, C2
+ wmov A4, C4
+ wmov A6, C6
+ ;; Move the Sign of the Result to SS.7
+ lsl SS
+
+6: ret
+
+ENDF __udivmod64
+#endif /* L_udivmod64 */
+
+
+#if defined (L_divdi3)
+
+;; R25:R18 = R24:R18 mod R17:R10
+;; Ordinary ABI-Function
+
+DEFUN __moddi3
+ set
+ rjmp __divdi3_moddi3
+ENDF __moddi3
+
+;; R25:R18 = R24:R18 div R17:R10
+;; Ordinary ABI-Function
+
+DEFUN __divdi3
+ clt
+ENDF __divdi3
+
+DEFUN __divdi3_moddi3
+#if SPEED_DIV
+ mov r31, A7
+ or r31, B7
+ brmi 0f
+ ;; Both Signs are 0: the following Complexitiy is not needed
+ XJMP __udivdi3_umoddi3
+#endif /* SPEED_DIV */
+
+0: ;; The Prologue
+ ;; Save Z = 12 Registers: Y, 17...8
+ ;; No Frame needed (X = 0)
+ clr r26
+ clr r27
+ ldi r30, lo8(gs(1f))
+ ldi r31, hi8(gs(1f))
+ XJMP __prologue_saves__ + ((18 - 12) * 2)
+
+1: ;; SS.7 will contain the Sign of the Quotient (A.sign * B.sign)
+ ;; SS.6 will contain the Sign of the Remainder (A.sign)
+ mov SS, A7
+ asr SS
+ ;; Adjust Dividend's Sign as needed
+#if SPEED_DIV
+ ;; Compiling for Speed we know that at least one Sign must be < 0
+ ;; Thus, if A[] >= 0 then we know B[] < 0
+ brpl 22f
+#else
+ brpl 21f
+#endif /* SPEED_DIV */
+
+ XCALL __negdi2
+
+ ;; Adjust Divisor's Sign and SS.7 as needed
+21: tst B7
+ brpl 3f
+22: ldi NN, 1 << 7
+ eor SS, NN
+
+ ldi NN, -1
+ com B4 $ com B5 $ com B6 $ com B7
+ $ com B1 $ com B2 $ com B3
+ NEG B0
+ $ sbc B1,NN $ sbc B2,NN $ sbc B3,NN
+ sbc B4,NN $ sbc B5,NN $ sbc B6,NN $ sbc B7,NN
+
+3: ;; Do the unsigned 64-Bit Division/Modulo (depending on T-flag)
+ XCALL __udivmod64
+
+ ;; Adjust Result's Sign
+#ifdef __AVR_ERRATA_SKIP_JMP_CALL__
+ tst SS
+ brpl 4f
+#else
+ sbrc SS, 7
+#endif /* __AVR_HAVE_JMP_CALL__ */
+ XCALL __negdi2
+
+4: ;; Epilogue: Restore the Z = 12 Registers and return
+ in r28, __SP_L__
+ in r29, __SP_H__
+ ldi r30, 12
+ XJMP __epilogue_restores__ + ((18 - 12) * 2)
+
+ENDF __divdi3_moddi3
+
+#undef R_cnt
+#undef SS
+#undef NN
+
+#endif /* L_divdi3 */
+
+#if defined (L_negdi2)
+DEFUN __negdi2
+
+ com A4 $ com A5 $ com A6 $ com A7
+ $ com A1 $ com A2 $ com A3
+ NEG A0
+ $ sbci A1,-1 $ sbci A2,-1 $ sbci A3,-1
+ sbci A4,-1 $ sbci A5,-1 $ sbci A6,-1 $ sbci A7,-1
+ ret
+
+ENDF __negdi2
+#endif /* L_negdi2 */
+
+#undef C7
+#undef C6
+#undef C5
+#undef C4
+#undef C3
+#undef C2
+#undef C1
+#undef C0
+
+#undef B7
+#undef B6
+#undef B5
+#undef B4
+#undef B3
+#undef B2
+#undef B1
+#undef B0
+
+#undef A7
+#undef A6
+#undef A5
+#undef A4
+#undef A3
+#undef A2
+#undef A1
+#undef A0
+
.section .text.libgcc.prologue, "ax", @progbits
@@ -854,6 +1209,7 @@ ENDF __divmodsi4
**********************************/
#if defined (L_prologue)
+;; This function does not clobber T-flag; 64-bit division relies on it
DEFUN __prologue_saves__
push r2
push r3
@@ -1181,6 +1537,119 @@ DEFUN __tablejump_elpm__
ENDF __tablejump_elpm__
#endif /* defined (L_tablejump_elpm) */
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Loading n bytes from Flash; n = 3,4
+;; R22... = Flash[Z]
+;; Clobbers: __tmp_reg__
+
+#if (defined (L_load_3) \
+ || defined (L_load_4)) \
+ && !defined (__AVR_HAVE_LPMX__)
+
+;; Destination
+#define D0 22
+#define D1 D0+1
+#define D2 D0+2
+#define D3 D0+3
+
+.macro .load dest, n
+ lpm
+ mov \dest, r0
+.if \dest != D0+\n-1
+ adiw r30, 1
+.else
+ sbiw r30, \n-1
+.endif
+.endm
+
+#if defined (L_load_3)
+DEFUN __load_3
+ push D3
+ XCALL __load_4
+ pop D3
+ ret
+ENDF __load_3
+#endif /* L_load_3 */
+
+#if defined (L_load_4)
+DEFUN __load_4
+ .load D0, 4
+ .load D1, 4
+ .load D2, 4
+ .load D3, 4
+ ret
+ENDF __load_4
+#endif /* L_load_4 */
+
+#endif /* L_load_3 || L_load_3 */
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Loading n bytes from Flash; n = 2,3,4
+;; R22... = Flash[R21:Z]
+;; Clobbers: __tmp_reg__, R21, R30, R31
+
+#if (defined (L_xload_2) \
+ || defined (L_xload_3) \
+ || defined (L_xload_4)) \
+ && defined (__AVR_HAVE_ELPM__) \
+ && !defined (__AVR_HAVE_ELPMX__)
+
+#if !defined (__AVR_HAVE_RAMPZ__)
+#error Need RAMPZ
+#endif /* have RAMPZ */
+
+;; Destination
+#define D0 22
+#define D1 D0+1
+#define D2 D0+2
+#define D3 D0+3
+
+;; Register containing bits 16+ of the address
+
+#define HHI8 21
+
+.macro .xload dest, n
+ elpm
+ mov \dest, r0
+.if \dest != D0+\n-1
+ adiw r30, 1
+ adc HHI8, __zero_reg__
+ out __RAMPZ__, HHI8
+.endif
+.endm
+
+#if defined (L_xload_2)
+DEFUN __xload_2
+ out __RAMPZ__, HHI8
+ .xload D0, 2
+ .xload D1, 2
+ ret
+ENDF __xload_2
+#endif /* L_xload_2 */
+
+#if defined (L_xload_3)
+DEFUN __xload_3
+ out __RAMPZ__, HHI8
+ .xload D0, 3
+ .xload D1, 3
+ .xload D2, 3
+ ret
+ENDF __xload_3
+#endif /* L_xload_3 */
+
+#if defined (L_xload_4)
+DEFUN __xload_4
+ out __RAMPZ__, HHI8
+ .xload D0, 4
+ .xload D1, 4
+ .xload D2, 4
+ .xload D3, 4
+ ret
+ENDF __xload_4
+#endif /* L_xload_4 */
+
+#endif /* L_xload_{2|3|4} && ELPM */
+
.section .text.libgcc.builtins, "ax", @progbits
diff --git a/libgcc/config/avr/t-avr b/libgcc/config/avr/t-avr
index cd529ae8606..b5c8d05186a 100644
--- a/libgcc/config/avr/t-avr
+++ b/libgcc/config/avr/t-avr
@@ -15,12 +15,17 @@ LIB1ASMFUNCS = \
_divmodpsi4 _udivmodpsi4 \
_udivmodsi4 \
_divmodsi4 \
+ _divdi3 _udivdi3 \
+ _udivmod64 \
+ _negdi2 \
_prologue \
_epilogue \
_exit \
_cleanup \
_tablejump \
_tablejump_elpm \
+ _load_3 _load_4 \
+ _xload_2 _xload_3 _xload_4 \
_copy_data \
_clear_bss \
_ctors \
@@ -48,6 +53,7 @@ LIB1ASMFUNCS = \
_fmul _fmuls _fmulsu
LIB2FUNCS_EXCLUDE = \
+ _moddi3 _umoddi3 \
_clz
# We do not have the DF type.
diff --git a/libgcc/config/darwin-crt-tm.c b/libgcc/config/darwin-crt-tm.c
new file mode 100644
index 00000000000..23113374eea
--- /dev/null
+++ b/libgcc/config/darwin-crt-tm.c
@@ -0,0 +1,77 @@
+/* Provide the runtime infrastructure for the transactional memory lib.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+ Contributed by Iain Sandoe <iains@gcc.gnu.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/>. */
+
+#include <mach-o/dyld.h>
+
+/* not listed in mach-o/dyld.h for some reason. */
+extern char * getsectdata (const char*,const char*,unsigned long*);
+
+#define WEAK __attribute__((weak))
+
+extern void _ITM_registerTMCloneTable (void *, size_t) WEAK;
+extern void _ITM_deregisterTMCloneTable (void *) WEAK;
+
+#ifdef START
+
+void __doTMRegistrations (void) __attribute__ ((constructor));
+
+void __doTMRegistrations (void)
+{
+ char * tm_clone_table_sect_data;
+ unsigned long tmct_siz;
+
+ tm_clone_table_sect_data = getsectdata ("__DATA",
+ "__tm_clone_table",
+ &tmct_siz);
+ tmct_siz /= (sizeof (size_t) * 2);
+ if (_ITM_registerTMCloneTable != NULL
+ && tm_clone_table_sect_data != NULL
+ && tmct_siz > 0)
+ _ITM_registerTMCloneTable (tm_clone_table_sect_data, (size_t)tmct_siz);
+}
+
+#endif
+
+#ifdef END
+
+void __doTMdeRegistrations (void) __attribute__ ((destructor));
+
+void __doTMdeRegistrations (void)
+{
+ char * tm_clone_table_sect_data;
+ unsigned long tmct_siz;
+
+ tm_clone_table_sect_data = getsectdata ("__DATA",
+ "__tm_clone_table",
+ &tmct_siz);
+
+ if (_ITM_deregisterTMCloneTable != NULL
+ && tm_clone_table_sect_data != NULL
+ && tmct_siz > 0)
+ _ITM_deregisterTMCloneTable (tm_clone_table_sect_data);
+
+}
+
+#endif
diff --git a/libgcc/config/i386/t-darwin64 b/libgcc/config/i386/t-darwin64
deleted file mode 100644
index 30cf58b38f9..00000000000
--- a/libgcc/config/i386/t-darwin64
+++ /dev/null
@@ -1,2 +0,0 @@
-LIB2_SIDITI_CONV_FUNCS = yes
-LIB2ADD = $(srcdir)/config/darwin-64.c
diff --git a/libgcc/config/m68k/linux-atomic.c b/libgcc/config/m68k/linux-atomic.c
new file mode 100644
index 00000000000..6e81d6b5d5e
--- /dev/null
+++ b/libgcc/config/m68k/linux-atomic.c
@@ -0,0 +1,211 @@
+/* Linux-specific atomic operations for m68k Linux.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+ Based on code contributed by CodeSourcery for ARM EABI Linux.
+
+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/>. */
+
+/* Coldfire dropped the CAS instruction from the base M68K ISA.
+
+ GCC automatically issues a asm memory barrier when it encounters
+ a __sync_synchronize builtin. Thus, we do not need to define this
+ builtin.
+
+ We implement byte, short and int versions of each atomic operation
+ using the kernel helper defined below. There is no support for
+ 64-bit operations yet. */
+
+#include <asm/unistd.h>
+#include <stdbool.h>
+
+#ifndef __NR_atomic_cmpxchg_32
+#define __NR_atomic_cmpxchg_32 335
+#endif
+
+/* Kernel helper for compare-and-exchange a 32-bit value. */
+static inline unsigned
+__kernel_cmpxchg (unsigned *mem, unsigned oldval, unsigned newval)
+{
+ register unsigned *a0 asm("a0") = mem;
+ register unsigned d2 asm("d2") = oldval;
+ register unsigned d1 asm("d1") = newval;
+ register unsigned d0 asm("d0") = __NR_atomic_cmpxchg_32;
+
+ asm volatile ("trap #0"
+ : "=r"(d0), "=r"(d1), "=r"(a0)
+ : "r"(d0), "r"(d1), "r"(d2), "r"(a0)
+ : "memory", "a1");
+
+ return d0;
+}
+
+#define HIDDEN __attribute__ ((visibility ("hidden")))
+
+/* Big endian masks */
+#define INVERT_MASK_1 24
+#define INVERT_MASK_2 16
+
+#define MASK_1 0xffu
+#define MASK_2 0xffffu
+
+#define NAME_oldval(OP, WIDTH) __sync_fetch_and_##OP##_##WIDTH
+#define NAME_newval(OP, WIDTH) __sync_##OP##_and_fetch_##WIDTH
+
+#define WORD_SYNC_OP(OP, PFX_OP, INF_OP, RETURN) \
+ unsigned HIDDEN \
+ NAME##_##RETURN (OP, 4) (unsigned *ptr, unsigned val) \
+ { \
+ unsigned oldval, newval, cmpval = *ptr; \
+ \
+ do { \
+ oldval = cmpval; \
+ newval = PFX_OP (oldval INF_OP val); \
+ cmpval = __kernel_cmpxchg (ptr, oldval, newval); \
+ } while (__builtin_expect (oldval != cmpval, 0)); \
+ \
+ return RETURN; \
+ }
+
+#define SUBWORD_SYNC_OP(OP, PFX_OP, INF_OP, TYPE, WIDTH, RETURN) \
+ TYPE HIDDEN \
+ NAME##_##RETURN (OP, WIDTH) (TYPE *ptr, TYPE sval) \
+ { \
+ unsigned *wordptr = (unsigned *) ((unsigned long) ptr & ~3); \
+ unsigned int mask, shift, oldval, newval, cmpval, wval; \
+ \
+ shift = (((unsigned long) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH; \
+ mask = MASK_##WIDTH << shift; \
+ wval = (sval & MASK_##WIDTH) << shift; \
+ \
+ cmpval = *wordptr; \
+ do { \
+ oldval = cmpval; \
+ newval = PFX_OP (oldval INF_OP wval); \
+ newval = (newval & mask) | (oldval & ~mask); \
+ cmpval = __kernel_cmpxchg (wordptr, oldval, newval); \
+ } while (__builtin_expect (oldval != cmpval, 0)); \
+ \
+ return (RETURN >> shift) & MASK_##WIDTH; \
+ }
+
+WORD_SYNC_OP (add, , +, oldval)
+WORD_SYNC_OP (sub, , -, oldval)
+WORD_SYNC_OP (or, , |, oldval)
+WORD_SYNC_OP (and, , &, oldval)
+WORD_SYNC_OP (xor, , ^, oldval)
+WORD_SYNC_OP (nand, ~, &, oldval)
+
+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)
+
+WORD_SYNC_OP (add, , +, newval)
+WORD_SYNC_OP (sub, , -, newval)
+WORD_SYNC_OP (or, , |, newval)
+WORD_SYNC_OP (and, , &, newval)
+WORD_SYNC_OP (xor, , ^, newval)
+WORD_SYNC_OP (nand, ~, &, newval)
+
+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)
+
+unsigned HIDDEN
+__sync_val_compare_and_swap_4 (unsigned *ptr, unsigned oldval, unsigned newval)
+{
+ return __kernel_cmpxchg (ptr, oldval, newval);
+}
+
+bool HIDDEN
+__sync_bool_compare_and_swap_4 (unsigned *ptr, unsigned oldval,
+ unsigned newval)
+{
+ return __kernel_cmpxchg (ptr, oldval, newval) == oldval;
+}
+
+#define SUBWORD_VAL_CAS(TYPE, WIDTH) \
+ TYPE HIDDEN \
+ __sync_val_compare_and_swap_##WIDTH (TYPE *ptr, TYPE soldval, \
+ TYPE snewval) \
+ { \
+ unsigned *wordptr = (unsigned *)((unsigned long) ptr & ~3); \
+ unsigned int mask, shift, woldval, wnewval; \
+ unsigned oldval, newval, cmpval; \
+ \
+ shift = (((unsigned long) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH; \
+ mask = MASK_##WIDTH << shift; \
+ woldval = (soldval & MASK_##WIDTH) << shift; \
+ wnewval = (snewval & MASK_##WIDTH) << shift; \
+ cmpval = *wordptr; \
+ \
+ do { \
+ oldval = cmpval; \
+ if ((oldval & mask) != woldval) \
+ break; \
+ newval = (oldval & ~mask) | wnewval; \
+ cmpval = __kernel_cmpxchg (wordptr, oldval, newval); \
+ } while (__builtin_expect (oldval != cmpval, 0)); \
+ \
+ return (oldval >> shift) & MASK_##WIDTH; \
+ }
+
+SUBWORD_VAL_CAS (unsigned short, 2)
+SUBWORD_VAL_CAS (unsigned char, 1)
+
+#define SUBWORD_BOOL_CAS(TYPE, WIDTH) \
+ bool HIDDEN \
+ __sync_bool_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval, \
+ TYPE newval) \
+ { \
+ return (__sync_val_compare_and_swap_##WIDTH (ptr, oldval, newval) \
+ == oldval); \
+ }
+
+SUBWORD_BOOL_CAS (unsigned short, 2)
+SUBWORD_BOOL_CAS (unsigned char, 1)
+
+#undef NAME_oldval
+#define NAME_oldval(OP, WIDTH) __sync_lock_##OP##_##WIDTH
+#define COMMA ,
+
+WORD_SYNC_OP (test_and_set, , COMMA, oldval)
+SUBWORD_SYNC_OP (test_and_set, , COMMA, unsigned short, 1, oldval)
+SUBWORD_SYNC_OP (test_and_set, , COMMA, unsigned short, 2, oldval)
diff --git a/libgcc/config/m68k/t-linux b/libgcc/config/m68k/t-linux
new file mode 100644
index 00000000000..06f0fe09f25
--- /dev/null
+++ b/libgcc/config/m68k/t-linux
@@ -0,0 +1 @@
+LIB2ADD_ST = $(srcdir)/config/m68k/linux-atomic.c
diff --git a/libgcc/config/rs6000/t-ppccomm b/libgcc/config/rs6000/t-ppccomm
index e9233688268..fb812d3801f 100644
--- a/libgcc/config/rs6000/t-ppccomm
+++ b/libgcc/config/rs6000/t-ppccomm
@@ -1,27 +1,8 @@
LIB2ADD += $(srcdir)/config/rs6000/ibm-ldouble.c \
$(srcdir)/config/rs6000/tramp.S
-# These can't end up in shared libgcc
+# This 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
diff --git a/libgcc/config/rs6000/t-ppccomm-ldbl b/libgcc/config/rs6000/t-ppccomm-ldbl
deleted file mode 100644
index f1d53606677..00000000000
--- a/libgcc/config/rs6000/t-ppccomm-ldbl
+++ /dev/null
@@ -1 +0,0 @@
-LIB2ADD += $(srcdir)/config/rs6000/ibm-ldouble.c
diff --git a/libgcc/config/rs6000/t-savresfgpr b/libgcc/config/rs6000/t-savresfgpr
new file mode 100644
index 00000000000..e2a951abd3f
--- /dev/null
+++ b/libgcc/config/rs6000/t-savresfgpr
@@ -0,0 +1,21 @@
+# 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
diff --git a/libgcc/config/sh/t-netbsd b/libgcc/config/sh/t-netbsd
index d4df407fa16..3c5739e2ffc 100644
--- a/libgcc/config/sh/t-netbsd
+++ b/libgcc/config/sh/t-netbsd
@@ -1,5 +1,3 @@
LIB1ASMFUNCS_CACHE = _ic_invalidate
-LIB2ADD =
-
HOST_LIBGCC2_CFLAGS += -mieee
diff --git a/libgcc/config/t-darwin b/libgcc/config/t-darwin
index e32127e9d8a..3365f010225 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 $<
+crttms.o: $(srcdir)/config/darwin-crt-tm.c
+ $(crt_compile) $(DARWIN_EXTRA_CRT_BUILD_CFLAGS) -DSTART -c $<
+
+crttme.o: $(srcdir)/config/darwin-crt-tm.c
+ $(crt_compile) $(DARWIN_EXTRA_CRT_BUILD_CFLAGS) -DEND -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
diff --git a/libgcc/crtstuff.c b/libgcc/crtstuff.c
index 66b2cdf2446..77b8d4201cd 100644
--- a/libgcc/crtstuff.c
+++ b/libgcc/crtstuff.c
@@ -127,6 +127,10 @@ call_ ## FUNC (void) \
# define HIDDEN_DTOR_LIST_END
#endif
+#if !defined(USE_TM_CLONE_REGISTRY) && defined(OBJECT_FORMAT_ELF)
+# define USE_TM_CLONE_REGISTRY 1
+#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.
@@ -163,6 +167,10 @@ extern void __do_global_ctors_1 (void);
/* Likewise for _Jv_RegisterClasses. */
extern void _Jv_RegisterClasses (void *) TARGET_ATTRIBUTE_WEAK;
+/* Likewise for transactional memory clone tables. */
+extern void _ITM_registerTMCloneTable (void *, size_t) TARGET_ATTRIBUTE_WEAK;
+extern void _ITM_deregisterTMCloneTable (void *) TARGET_ATTRIBUTE_WEAK;
+
#ifdef OBJECT_FORMAT_ELF
/* Declare a pointer to void function type. */
@@ -242,6 +250,55 @@ STATIC void *__JCR_LIST__[]
= { };
#endif /* JCR_SECTION_NAME */
+#if USE_TM_CLONE_REGISTRY
+STATIC func_ptr __TMC_LIST__[]
+ __attribute__((used, section(".tm_clone_table"), aligned(sizeof(void*))))
+ = { };
+# ifdef HAVE_GAS_HIDDEN
+extern func_ptr __TMC_END__[] __attribute__((__visibility__ ("hidden")));
+# endif
+
+static inline void
+deregister_tm_clones (void)
+{
+ void (*fn) (void *);
+
+#ifdef HAVE_GAS_HIDDEN
+ if (__TMC_END__ - __TMC_LIST__ == 0)
+ return;
+#else
+ if (__TMC_LIST__[0] == NULL)
+ return;
+#endif
+
+ fn = _ITM_deregisterTMCloneTable;
+ __asm ("" : "+r" (fn));
+ if (fn)
+ fn (__TMC_LIST__);
+}
+
+static inline void
+register_tm_clones (void)
+{
+ void (*fn) (void *, size_t);
+ size_t size;
+
+#ifdef HAVE_GAS_HIDDEN
+ size = (__TMC_END__ - __TMC_LIST__) / 2;
+#else
+ for (size = 0; __TMC_LIST__[size * 2] != NULL; size++)
+ continue;
+#endif
+ if (size == 0)
+ return;
+
+ fn = _ITM_registerTMCloneTable;
+ __asm ("" : "+r" (fn));
+ if (fn)
+ fn (__TMC_LIST__, size);
+}
+#endif /* USE_TM_CLONE_REGISTRY */
+
#if defined(INIT_SECTION_ASM_OP) || defined(INIT_ARRAY_SECTION_ASM_OP)
#ifdef OBJECT_FORMAT_ELF
@@ -331,6 +388,10 @@ __do_global_dtors_aux (void)
}
#endif /* !defined(FINI_ARRAY_SECTION_ASM_OP) */
+#if USE_TM_CLONE_REGISTRY
+ deregister_tm_clones ();
+#endif /* USE_TM_CLONE_REGISTRY */
+
#ifdef USE_EH_FRAME_REGISTRY
#ifdef CRT_GET_RFIB_DATA
/* If we used the new __register_frame_info_bases interface,
@@ -362,7 +423,9 @@ __do_global_dtors_aux_1 (void)
CRT_CALL_STATIC_FUNCTION (INIT_SECTION_ASM_OP, __do_global_dtors_aux_1)
#endif
-#if defined(USE_EH_FRAME_REGISTRY) || defined(JCR_SECTION_NAME)
+#if defined(USE_EH_FRAME_REGISTRY) \
+ || defined(JCR_SECTION_NAME) \
+ || defined(USE_TM_CLONE_REGISTRY)
/* 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. */
@@ -383,6 +446,7 @@ frame_dummy (void)
__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])
{
@@ -392,6 +456,10 @@ frame_dummy (void)
register_classes (__JCR_LIST__);
}
#endif /* JCR_SECTION_NAME */
+
+#if USE_TM_CLONE_REGISTRY
+ register_tm_clones ();
+#endif /* USE_TM_CLONE_REGISTRY */
}
#ifdef INIT_SECTION_ASM_OP
@@ -401,7 +469,7 @@ 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 */
+#endif /* USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME || USE_TM_CLONE_REGISTRY */
#else /* OBJECT_FORMAT_ELF */
@@ -458,13 +526,19 @@ __do_global_dtors (void)
for (p = __DTOR_LIST__ + 1; (f = *p); p++)
f ();
+#if USE_TM_CLONE_REGISTRY
+ deregister_tm_clones ();
+#endif /* USE_TM_CLONE_REGISTRY */
+
#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)
+#if defined(USE_EH_FRAME_REGISTRY) \
+ || defined(JCR_SECTION_NAME) \
+ || defined(USE_TM_CLONE_REGISTRY)
/* 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
@@ -477,6 +551,7 @@ __do_global_ctors_1(void)
if (__register_frame_info)
__register_frame_info (__EH_FRAME_BEGIN__, &object);
#endif
+
#ifdef JCR_SECTION_NAME
if (__JCR_LIST__[0])
{
@@ -486,8 +561,12 @@ __do_global_ctors_1(void)
register_classes (__JCR_LIST__);
}
#endif
+
+#if USE_TM_CLONE_REGISTRY
+ register_tm_clones ();
+#endif /* USE_TM_CLONE_REGISTRY */
}
-#endif /* USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME */
+#endif /* USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME || USE_TM_CLONE_REGISTRY */
#else /* ! INIT_SECTION_ASM_OP && ! HAS_INIT_SECTION */
#error "What are you doing with crtstuff.c, then?"
@@ -571,6 +650,19 @@ STATIC void *__JCR_END__[1]
= { 0 };
#endif /* JCR_SECTION_NAME */
+#if USE_TM_CLONE_REGISTRY
+# ifndef HAVE_GAS_HIDDEN
+static
+# endif
+func_ptr __TMC_END__[]
+ __attribute__((used, section(".tm_clone_table"), aligned(sizeof(void *))))
+# ifdef HAVE_GAS_HIDDEN
+ __attribute__((__visibility__ ("hidden"))) = { };
+# else
+ = { 0, 0 };
+# endif
+#endif /* USE_TM_CLONE_REGISTRY */
+
#ifdef INIT_ARRAY_SECTION_ASM_OP
/* If we are using .init_array, there is nothing to do. */
@@ -635,7 +727,9 @@ void
__do_global_ctors (void)
{
func_ptr *p;
-#if defined(USE_EH_FRAME_REGISTRY) || defined(JCR_SECTION_NAME)
+#if defined(USE_EH_FRAME_REGISTRY) \
+ || defined(JCR_SECTION_NAME) \
+ || defined(USE_TM_CLONE_REGISTRY)
__do_global_ctors_1();
#endif
for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
diff --git a/libgcc/generic-morestack.c b/libgcc/generic-morestack.c
index 00a3b1c3bf0..4dbaa0e4cdc 100644
--- a/libgcc/generic-morestack.c
+++ b/libgcc/generic-morestack.c
@@ -115,6 +115,14 @@ extern void *
__splitstack_makecontext (size_t, void *context[10], size_t *)
__attribute__ ((visibility ("default")));
+extern void *
+__splitstack_resetcontext (void *context[10], size_t *)
+ __attribute__ ((visibility ("default")));
+
+extern void
+__splitstack_releasecontext (void *context[10])
+ __attribute__ ((visibility ("default")));
+
extern void
__splitstack_block_signals_context (void *context[10], int *, int *)
__attribute__ ((visibility ("default")));
@@ -911,15 +919,23 @@ __splitstack_find (void *segment_arg, void *sp, size_t *len,
nsp = (char *) segment->old_stack;
+ if (nsp == NULL)
+ {
+ /* We've reached the top of the stack. */
+ *next_segment = (void *) (uintptr_type) 2;
+ }
+ else
+ {
#if defined (__x86_64__)
- nsp -= 12 * sizeof (void *);
+ nsp -= 12 * sizeof (void *);
#elif defined (__i386__)
- nsp -= 6 * sizeof (void *);
+ nsp -= 6 * sizeof (void *);
#else
#error "unrecognized target"
#endif
- *next_sp = (void *) nsp;
+ *next_sp = (void *) nsp;
+ }
#ifdef STACK_GROWS_DOWNWARD
*len = (char *) (segment + 1) + segment->size - (char *) sp;
@@ -1037,6 +1053,60 @@ __splitstack_makecontext (size_t stack_size, void *context[NUMBER_OFFSETS],
return (void *) (segment + 1);
}
+/* Given an existing split stack context, reset it back to the start
+ of the stack. Return the stack pointer and size, appropriate for
+ use with makecontext. This may be used if a coroutine exits, in
+ order to reuse the stack segments for a new coroutine. */
+
+void *
+__splitstack_resetcontext (void *context[10], size_t *size)
+{
+ struct stack_segment *segment;
+ void *initial_sp;
+ size_t initial_size;
+ void *ret;
+
+ /* Reset the context assuming that MORESTACK_SEGMENTS, INITIAL_SP
+ and INITIAL_SP_LEN are correct. */
+
+ segment = context[MORESTACK_SEGMENTS];
+ context[CURRENT_SEGMENT] = segment;
+ context[CURRENT_STACK] = NULL;
+ if (segment == NULL)
+ {
+ initial_sp = context[INITIAL_SP];
+ initial_size = (uintptr_type) context[INITIAL_SP_LEN];
+ ret = initial_sp;
+#ifdef STACK_GROWS_DOWNWARD
+ ret = (void *) ((char *) ret - initial_size);
+#endif
+ }
+ else
+ {
+#ifdef STACK_GROWS_DOWNWARD
+ initial_sp = (void *) ((char *) (segment + 1) + segment->size);
+#else
+ initial_sp = (void *) (segment + 1);
+#endif
+ initial_size = segment->size;
+ ret = (void *) (segment + 1);
+ }
+ context[STACK_GUARD] = __morestack_make_guard (initial_sp, initial_size);
+ context[BLOCK_SIGNALS] = NULL;
+ *size = initial_size;
+ return ret;
+}
+
+/* Release all the memory associated with a splitstack context. This
+ may be used if a coroutine exits and the associated stack should be
+ freed. */
+
+void
+__splitstack_releasecontext (void *context[10])
+{
+ __morestack_release_segments (context[MORESTACK_SEGMENTS], 1);
+}
+
/* Like __splitstack_block_signals, but operating on CONTEXT, rather
than on the current state. */
diff --git a/libgcc/libgcc-std.ver.in b/libgcc/libgcc-std.ver.in
index 2d66612d1c5..ec702952f9b 100644
--- a/libgcc/libgcc-std.ver.in
+++ b/libgcc/libgcc-std.ver.in
@@ -1932,4 +1932,6 @@ GCC_4.7.0 {
__splitstack_makecontext
__splitstack_block_signals_context
__splitstack_find_context
+ __splitstack_resetcontext
+ __splitstack_releasecontext
}
diff --git a/libgcc/static-object.mk b/libgcc/static-object.mk
index ab75d3288c3..930f009cd42 100644
--- a/libgcc/static-object.mk
+++ b/libgcc/static-object.mk
@@ -6,10 +6,15 @@ iter-items := $(filter-out $o,$(iter-items))
base := $(basename $(notdir $o))
+# Copy c_flags to a rule-specific copy and use the copy, to avoid the
+# following rules being affected by later changes to c_flags in the
+# including file.
+c_flags-$o := $(c_flags)
+
ifeq ($(suffix $o),.c)
$(base)$(objext): $o
- $(gcc_compile) $(c_flags) -c $< $(vis_hide)
+ $(gcc_compile) $(c_flags-$<) -c $< $(vis_hide)
else
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 6c253b0d0cc..750428fec7a 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,7 @@
+2011-11-21 Andreas Tobler <andreast@fgznet.ch>
+
+ * configure: Regenerate.
+
2011-11-11 Janne Blomqvist <jb@gcc.gnu.org>
PR libfortran/51090
diff --git a/libgfortran/configure b/libgfortran/configure
index c39b003e9e4..6ae1f09f48c 100755
--- a/libgfortran/configure
+++ b/libgfortran/configure
@@ -10532,7 +10532,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct=yes
hardcode_minus_L=yes
@@ -11448,7 +11448,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -11466,7 +11466,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
@@ -14368,7 +14368,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
archive_cmds_FC='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct_FC=yes
hardcode_minus_L_FC=yes
@@ -15076,7 +15076,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -15094,7 +15094,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
diff --git a/libgo/Makefile.am b/libgo/Makefile.am
index 00e97d2dc8d..c30d9c36c2b 100644
--- a/libgo/Makefile.am
+++ b/libgo/Makefile.am
@@ -394,6 +394,12 @@ else
rtems_task_variable_add_file =
endif
+if LIBGO_IS_LINUX
+runtime_lock_files = runtime/lock_futex.c runtime/thread-linux.c
+else
+runtime_lock_files = runtime/lock_sema.c runtime/thread-sema.c
+endif
+
runtime_files = \
runtime/go-append.c \
runtime/go-assert.c \
@@ -415,14 +421,11 @@ runtime_files = \
runtime/go-eface-compare.c \
runtime/go-eface-val-compare.c \
runtime/go-getgoroot.c \
- runtime/go-go.c \
- runtime/go-gomaxprocs.c \
runtime/go-int-array-to-string.c \
runtime/go-int-to-string.c \
runtime/go-interface-compare.c \
runtime/go-interface-eface-compare.c \
runtime/go-interface-val-compare.c \
- runtime/go-lock-os-thread.c \
runtime/go-make-slice.c \
runtime/go-map-delete.c \
runtime/go-map-index.c \
@@ -432,10 +435,8 @@ runtime_files = \
runtime/go-new-channel.c \
runtime/go-new-map.c \
runtime/go-new.c \
- runtime/go-note.c \
runtime/go-panic.c \
runtime/go-print.c \
- runtime/go-rand.c \
runtime/go-rec-big.c \
runtime/go-rec-nb-big.c \
runtime/go-rec-nb-small.c \
@@ -447,9 +448,7 @@ runtime_files = \
runtime/go-reflect-map.c \
runtime/go-rune.c \
runtime/go-runtime-error.c \
- runtime/go-sched.c \
runtime/go-select.c \
- runtime/go-semacquire.c \
runtime/go-send-big.c \
runtime/go-send-nb-big.c \
runtime/go-send-nb-small.c \
@@ -475,6 +474,7 @@ runtime_files = \
runtime/go-unsafe-pointer.c \
runtime/go-unwind.c \
runtime/cpuprof.c \
+ $(runtime_lock_files) \
runtime/mcache.c \
runtime/mcentral.c \
$(runtime_mem_file) \
@@ -484,6 +484,7 @@ runtime_files = \
runtime/mheap.c \
runtime/msize.c \
runtime/proc.c \
+ runtime/runtime.c \
runtime/thread.c \
runtime/yield.c \
$(rtems_task_variable_add_file) \
@@ -493,6 +494,8 @@ runtime_files = \
map.c \
mprof.c \
reflect.c \
+ runtime1.c \
+ sema.c \
sigqueue.c \
string.c
@@ -514,6 +517,14 @@ reflect.c: $(srcdir)/runtime/reflect.goc goc2c
./goc2c --gcc --go-prefix libgo_reflect $< > $@.tmp
mv -f $@.tmp $@
+runtime1.c: $(srcdir)/runtime/runtime1.goc goc2c
+ ./goc2c --gcc --go-prefix libgo_runtime $< > $@.tmp
+ mv -f $@.tmp $@
+
+sema.c: $(srcdir)/runtime/sema.goc goc2c
+ ./goc2c --gcc --go-prefix libgo_runtime $< > $@.tmp
+ mv -f $@.tmp $@
+
sigqueue.c: $(srcdir)/runtime/sigqueue.goc goc2c
./goc2c --gcc --go-prefix libgo_runtime $< > $@.tmp
mv -f $@.tmp $@
diff --git a/libgo/Makefile.in b/libgo/Makefile.in
index 68b972e16d4..8b6bb728272 100644
--- a/libgo/Makefile.in
+++ b/libgo/Makefile.in
@@ -189,26 +189,24 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
runtime/go-copy.c runtime/go-defer.c \
runtime/go-deferred-recover.c runtime/go-eface-compare.c \
runtime/go-eface-val-compare.c runtime/go-getgoroot.c \
- runtime/go-go.c runtime/go-gomaxprocs.c \
runtime/go-int-array-to-string.c runtime/go-int-to-string.c \
runtime/go-interface-compare.c \
runtime/go-interface-eface-compare.c \
- runtime/go-interface-val-compare.c runtime/go-lock-os-thread.c \
- runtime/go-make-slice.c runtime/go-map-delete.c \
- runtime/go-map-index.c runtime/go-map-len.c \
- runtime/go-map-range.c runtime/go-nanotime.c \
- runtime/go-new-channel.c runtime/go-new-map.c runtime/go-new.c \
- runtime/go-note.c runtime/go-panic.c runtime/go-print.c \
- runtime/go-rand.c runtime/go-rec-big.c runtime/go-rec-nb-big.c \
- runtime/go-rec-nb-small.c runtime/go-rec-small.c \
- runtime/go-recover.c runtime/go-reflect.c \
- runtime/go-reflect-call.c runtime/go-reflect-chan.c \
- runtime/go-reflect-map.c runtime/go-rune.c \
- runtime/go-runtime-error.c runtime/go-sched.c \
- runtime/go-select.c runtime/go-semacquire.c \
- runtime/go-send-big.c runtime/go-send-nb-big.c \
- runtime/go-send-nb-small.c runtime/go-send-small.c \
- runtime/go-setenv.c runtime/go-signal.c runtime/go-strcmp.c \
+ runtime/go-interface-val-compare.c runtime/go-make-slice.c \
+ runtime/go-map-delete.c runtime/go-map-index.c \
+ runtime/go-map-len.c runtime/go-map-range.c \
+ runtime/go-nanotime.c runtime/go-new-channel.c \
+ runtime/go-new-map.c runtime/go-new.c runtime/go-panic.c \
+ runtime/go-print.c runtime/go-rec-big.c \
+ runtime/go-rec-nb-big.c runtime/go-rec-nb-small.c \
+ runtime/go-rec-small.c runtime/go-recover.c \
+ runtime/go-reflect.c runtime/go-reflect-call.c \
+ runtime/go-reflect-chan.c runtime/go-reflect-map.c \
+ runtime/go-rune.c runtime/go-runtime-error.c \
+ runtime/go-select.c runtime/go-send-big.c \
+ runtime/go-send-nb-big.c runtime/go-send-nb-small.c \
+ runtime/go-send-small.c runtime/go-setenv.c \
+ runtime/go-signal.c runtime/go-strcmp.c \
runtime/go-string-to-byte-array.c \
runtime/go-string-to-int-array.c runtime/go-strplus.c \
runtime/go-strslice.c runtime/go-trampoline.c \
@@ -218,45 +216,48 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
runtime/go-typestring.c runtime/go-unreflect.c \
runtime/go-unsafe-new.c runtime/go-unsafe-newarray.c \
runtime/go-unsafe-pointer.c runtime/go-unwind.c \
- runtime/cpuprof.c runtime/mcache.c runtime/mcentral.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/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
-am__objects_3 = go-append.lo go-assert.lo go-assert-interface.lo \
+ runtime/cpuprof.c runtime/lock_sema.c runtime/thread-sema.c \
+ runtime/lock_futex.c runtime/thread-linux.c runtime/mcache.c \
+ runtime/mcentral.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/runtime.c runtime/thread.c runtime/yield.c \
+ runtime/rtems-task-variable-add.c chan.c iface.c malloc.c \
+ map.c mprof.c reflect.c runtime1.c sema.c sigqueue.c string.c
+@LIBGO_IS_LINUX_FALSE@am__objects_1 = lock_sema.lo thread-sema.lo
+@LIBGO_IS_LINUX_TRUE@am__objects_1 = lock_futex.lo thread-linux.lo
+@HAVE_SYS_MMAN_H_FALSE@am__objects_2 = mem_posix_memalign.lo
+@HAVE_SYS_MMAN_H_TRUE@am__objects_2 = mem.lo
+@LIBGO_IS_RTEMS_TRUE@am__objects_3 = rtems-task-variable-add.lo
+am__objects_4 = go-append.lo go-assert.lo go-assert-interface.lo \
go-byte-array-to-string.lo go-breakpoint.lo go-caller.lo \
go-can-convert-interface.lo go-cgo.lo go-chan-cap.lo \
go-chan-len.lo go-check-interface.lo go-close.lo \
go-construct-map.lo go-convert-interface.lo go-copy.lo \
go-defer.lo go-deferred-recover.lo go-eface-compare.lo \
- go-eface-val-compare.lo go-getgoroot.lo go-go.lo \
- go-gomaxprocs.lo go-int-array-to-string.lo go-int-to-string.lo \
+ go-eface-val-compare.lo go-getgoroot.lo \
+ go-int-array-to-string.lo go-int-to-string.lo \
go-interface-compare.lo go-interface-eface-compare.lo \
- go-interface-val-compare.lo go-lock-os-thread.lo \
- go-make-slice.lo go-map-delete.lo go-map-index.lo \
- go-map-len.lo go-map-range.lo go-nanotime.lo go-new-channel.lo \
- go-new-map.lo go-new.lo go-note.lo go-panic.lo go-print.lo \
- go-rand.lo go-rec-big.lo go-rec-nb-big.lo go-rec-nb-small.lo \
+ go-interface-val-compare.lo go-make-slice.lo go-map-delete.lo \
+ go-map-index.lo go-map-len.lo go-map-range.lo go-nanotime.lo \
+ go-new-channel.lo go-new-map.lo go-new.lo go-panic.lo \
+ go-print.lo go-rec-big.lo go-rec-nb-big.lo go-rec-nb-small.lo \
go-rec-small.lo go-recover.lo go-reflect.lo go-reflect-call.lo \
go-reflect-chan.lo go-reflect-map.lo go-rune.lo \
- go-runtime-error.lo go-sched.lo go-select.lo go-semacquire.lo \
- go-send-big.lo go-send-nb-big.lo go-send-nb-small.lo \
- go-send-small.lo go-setenv.lo go-signal.lo go-strcmp.lo \
+ go-runtime-error.lo go-select.lo go-send-big.lo \
+ go-send-nb-big.lo go-send-nb-small.lo go-send-small.lo \
+ go-setenv.lo go-signal.lo go-strcmp.lo \
go-string-to-byte-array.lo go-string-to-int-array.lo \
go-strplus.lo go-strslice.lo go-trampoline.lo go-type-eface.lo \
go-type-error.lo go-type-identity.lo go-type-interface.lo \
go-type-string.lo go-typedesc-equal.lo go-typestring.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 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)
+ go-unsafe-pointer.lo go-unwind.lo cpuprof.lo $(am__objects_1) \
+ mcache.lo mcentral.lo $(am__objects_2) mfinal.lo mfixalloc.lo \
+ mgc0.lo mheap.lo msize.lo proc.lo runtime.lo thread.lo \
+ yield.lo $(am__objects_3) chan.lo iface.lo malloc.lo map.lo \
+ mprof.lo reflect.lo runtime1.lo sema.lo sigqueue.lo string.lo
+am_libgo_la_OBJECTS = $(am__objects_4)
libgo_la_OBJECTS = $(am_libgo_la_OBJECTS)
libgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(libgo_la_LDFLAGS) \
@@ -824,6 +825,8 @@ toolexeclibgotesting_DATA = \
@HAVE_SYS_MMAN_H_TRUE@runtime_mem_file = runtime/mem.c
@LIBGO_IS_RTEMS_FALSE@rtems_task_variable_add_file =
@LIBGO_IS_RTEMS_TRUE@rtems_task_variable_add_file = runtime/rtems-task-variable-add.c
+@LIBGO_IS_LINUX_FALSE@runtime_lock_files = runtime/lock_sema.c runtime/thread-sema.c
+@LIBGO_IS_LINUX_TRUE@runtime_lock_files = runtime/lock_futex.c runtime/thread-linux.c
runtime_files = \
runtime/go-append.c \
runtime/go-assert.c \
@@ -845,14 +848,11 @@ runtime_files = \
runtime/go-eface-compare.c \
runtime/go-eface-val-compare.c \
runtime/go-getgoroot.c \
- runtime/go-go.c \
- runtime/go-gomaxprocs.c \
runtime/go-int-array-to-string.c \
runtime/go-int-to-string.c \
runtime/go-interface-compare.c \
runtime/go-interface-eface-compare.c \
runtime/go-interface-val-compare.c \
- runtime/go-lock-os-thread.c \
runtime/go-make-slice.c \
runtime/go-map-delete.c \
runtime/go-map-index.c \
@@ -862,10 +862,8 @@ runtime_files = \
runtime/go-new-channel.c \
runtime/go-new-map.c \
runtime/go-new.c \
- runtime/go-note.c \
runtime/go-panic.c \
runtime/go-print.c \
- runtime/go-rand.c \
runtime/go-rec-big.c \
runtime/go-rec-nb-big.c \
runtime/go-rec-nb-small.c \
@@ -877,9 +875,7 @@ runtime_files = \
runtime/go-reflect-map.c \
runtime/go-rune.c \
runtime/go-runtime-error.c \
- runtime/go-sched.c \
runtime/go-select.c \
- runtime/go-semacquire.c \
runtime/go-send-big.c \
runtime/go-send-nb-big.c \
runtime/go-send-nb-small.c \
@@ -905,6 +901,7 @@ runtime_files = \
runtime/go-unsafe-pointer.c \
runtime/go-unwind.c \
runtime/cpuprof.c \
+ $(runtime_lock_files) \
runtime/mcache.c \
runtime/mcentral.c \
$(runtime_mem_file) \
@@ -914,6 +911,7 @@ runtime_files = \
runtime/mheap.c \
runtime/msize.c \
runtime/proc.c \
+ runtime/runtime.c \
runtime/thread.c \
runtime/yield.c \
$(rtems_task_variable_add_file) \
@@ -923,6 +921,8 @@ runtime_files = \
map.c \
mprof.c \
reflect.c \
+ runtime1.c \
+ sema.c \
sigqueue.c \
string.c
@@ -2471,14 +2471,11 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-eface-compare.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-eface-val-compare.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-getgoroot.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-go.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-gomaxprocs.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-int-array-to-string.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-int-to-string.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-interface-compare.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-interface-eface-compare.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-interface-val-compare.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-lock-os-thread.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-make-slice.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-map-delete.Plo@am__quote@
@@ -2489,10 +2486,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-new-channel.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-new-map.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-new.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-note.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-panic.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-print.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rand.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rec-big.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rec-nb-big.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rec-nb-small.Plo@am__quote@
@@ -2504,9 +2499,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-reflect.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rune.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-runtime-error.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-sched.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-select.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-semacquire.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-send-big.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-send-nb-big.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-send-nb-small.Plo@am__quote@
@@ -2532,6 +2525,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsafe-pointer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unwind.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lock_futex.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lock_sema.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/malloc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcache.Plo@am__quote@
@@ -2547,8 +2542,13 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reflect.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rtems-task-variable-add.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/runtime.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/runtime1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sema.Plo@am__quote@
@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-linux.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread-sema.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@
@@ -2727,20 +2727,6 @@ go-getgoroot.lo: runtime/go-getgoroot.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 go-getgoroot.lo `test -f 'runtime/go-getgoroot.c' || echo '$(srcdir)/'`runtime/go-getgoroot.c
-go-go.lo: runtime/go-go.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-go.lo -MD -MP -MF $(DEPDIR)/go-go.Tpo -c -o go-go.lo `test -f 'runtime/go-go.c' || echo '$(srcdir)/'`runtime/go-go.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-go.Tpo $(DEPDIR)/go-go.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-go.c' object='go-go.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 go-go.lo `test -f 'runtime/go-go.c' || echo '$(srcdir)/'`runtime/go-go.c
-
-go-gomaxprocs.lo: runtime/go-gomaxprocs.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-gomaxprocs.lo -MD -MP -MF $(DEPDIR)/go-gomaxprocs.Tpo -c -o go-gomaxprocs.lo `test -f 'runtime/go-gomaxprocs.c' || echo '$(srcdir)/'`runtime/go-gomaxprocs.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-gomaxprocs.Tpo $(DEPDIR)/go-gomaxprocs.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-gomaxprocs.c' object='go-gomaxprocs.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 go-gomaxprocs.lo `test -f 'runtime/go-gomaxprocs.c' || echo '$(srcdir)/'`runtime/go-gomaxprocs.c
-
go-int-array-to-string.lo: runtime/go-int-array-to-string.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-int-array-to-string.lo -MD -MP -MF $(DEPDIR)/go-int-array-to-string.Tpo -c -o go-int-array-to-string.lo `test -f 'runtime/go-int-array-to-string.c' || echo '$(srcdir)/'`runtime/go-int-array-to-string.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-int-array-to-string.Tpo $(DEPDIR)/go-int-array-to-string.Plo
@@ -2776,13 +2762,6 @@ go-interface-val-compare.lo: runtime/go-interface-val-compare.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 go-interface-val-compare.lo `test -f 'runtime/go-interface-val-compare.c' || echo '$(srcdir)/'`runtime/go-interface-val-compare.c
-go-lock-os-thread.lo: runtime/go-lock-os-thread.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-lock-os-thread.lo -MD -MP -MF $(DEPDIR)/go-lock-os-thread.Tpo -c -o go-lock-os-thread.lo `test -f 'runtime/go-lock-os-thread.c' || echo '$(srcdir)/'`runtime/go-lock-os-thread.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-lock-os-thread.Tpo $(DEPDIR)/go-lock-os-thread.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-lock-os-thread.c' object='go-lock-os-thread.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 go-lock-os-thread.lo `test -f 'runtime/go-lock-os-thread.c' || echo '$(srcdir)/'`runtime/go-lock-os-thread.c
-
go-make-slice.lo: runtime/go-make-slice.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-make-slice.lo -MD -MP -MF $(DEPDIR)/go-make-slice.Tpo -c -o go-make-slice.lo `test -f 'runtime/go-make-slice.c' || echo '$(srcdir)/'`runtime/go-make-slice.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-make-slice.Tpo $(DEPDIR)/go-make-slice.Plo
@@ -2846,13 +2825,6 @@ go-new.lo: runtime/go-new.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 go-new.lo `test -f 'runtime/go-new.c' || echo '$(srcdir)/'`runtime/go-new.c
-go-note.lo: runtime/go-note.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-note.lo -MD -MP -MF $(DEPDIR)/go-note.Tpo -c -o go-note.lo `test -f 'runtime/go-note.c' || echo '$(srcdir)/'`runtime/go-note.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-note.Tpo $(DEPDIR)/go-note.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-note.c' object='go-note.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 go-note.lo `test -f 'runtime/go-note.c' || echo '$(srcdir)/'`runtime/go-note.c
-
go-panic.lo: runtime/go-panic.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-panic.lo -MD -MP -MF $(DEPDIR)/go-panic.Tpo -c -o go-panic.lo `test -f 'runtime/go-panic.c' || echo '$(srcdir)/'`runtime/go-panic.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-panic.Tpo $(DEPDIR)/go-panic.Plo
@@ -2867,13 +2839,6 @@ go-print.lo: runtime/go-print.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 go-print.lo `test -f 'runtime/go-print.c' || echo '$(srcdir)/'`runtime/go-print.c
-go-rand.lo: runtime/go-rand.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-rand.lo -MD -MP -MF $(DEPDIR)/go-rand.Tpo -c -o go-rand.lo `test -f 'runtime/go-rand.c' || echo '$(srcdir)/'`runtime/go-rand.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-rand.Tpo $(DEPDIR)/go-rand.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-rand.c' object='go-rand.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 go-rand.lo `test -f 'runtime/go-rand.c' || echo '$(srcdir)/'`runtime/go-rand.c
-
go-rec-big.lo: runtime/go-rec-big.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-rec-big.lo -MD -MP -MF $(DEPDIR)/go-rec-big.Tpo -c -o go-rec-big.lo `test -f 'runtime/go-rec-big.c' || echo '$(srcdir)/'`runtime/go-rec-big.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-rec-big.Tpo $(DEPDIR)/go-rec-big.Plo
@@ -2951,13 +2916,6 @@ go-runtime-error.lo: runtime/go-runtime-error.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 go-runtime-error.lo `test -f 'runtime/go-runtime-error.c' || echo '$(srcdir)/'`runtime/go-runtime-error.c
-go-sched.lo: runtime/go-sched.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-sched.lo -MD -MP -MF $(DEPDIR)/go-sched.Tpo -c -o go-sched.lo `test -f 'runtime/go-sched.c' || echo '$(srcdir)/'`runtime/go-sched.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-sched.Tpo $(DEPDIR)/go-sched.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-sched.c' object='go-sched.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 go-sched.lo `test -f 'runtime/go-sched.c' || echo '$(srcdir)/'`runtime/go-sched.c
-
go-select.lo: runtime/go-select.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-select.lo -MD -MP -MF $(DEPDIR)/go-select.Tpo -c -o go-select.lo `test -f 'runtime/go-select.c' || echo '$(srcdir)/'`runtime/go-select.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-select.Tpo $(DEPDIR)/go-select.Plo
@@ -2965,13 +2923,6 @@ go-select.lo: runtime/go-select.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 go-select.lo `test -f 'runtime/go-select.c' || echo '$(srcdir)/'`runtime/go-select.c
-go-semacquire.lo: runtime/go-semacquire.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-semacquire.lo -MD -MP -MF $(DEPDIR)/go-semacquire.Tpo -c -o go-semacquire.lo `test -f 'runtime/go-semacquire.c' || echo '$(srcdir)/'`runtime/go-semacquire.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-semacquire.Tpo $(DEPDIR)/go-semacquire.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-semacquire.c' object='go-semacquire.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 go-semacquire.lo `test -f 'runtime/go-semacquire.c' || echo '$(srcdir)/'`runtime/go-semacquire.c
-
go-send-big.lo: runtime/go-send-big.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-send-big.lo -MD -MP -MF $(DEPDIR)/go-send-big.Tpo -c -o go-send-big.lo `test -f 'runtime/go-send-big.c' || echo '$(srcdir)/'`runtime/go-send-big.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-send-big.Tpo $(DEPDIR)/go-send-big.Plo
@@ -3147,6 +3098,34 @@ cpuprof.lo: runtime/cpuprof.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 cpuprof.lo `test -f 'runtime/cpuprof.c' || echo '$(srcdir)/'`runtime/cpuprof.c
+lock_sema.lo: runtime/lock_sema.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lock_sema.lo -MD -MP -MF $(DEPDIR)/lock_sema.Tpo -c -o lock_sema.lo `test -f 'runtime/lock_sema.c' || echo '$(srcdir)/'`runtime/lock_sema.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lock_sema.Tpo $(DEPDIR)/lock_sema.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/lock_sema.c' object='lock_sema.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 lock_sema.lo `test -f 'runtime/lock_sema.c' || echo '$(srcdir)/'`runtime/lock_sema.c
+
+thread-sema.lo: runtime/thread-sema.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thread-sema.lo -MD -MP -MF $(DEPDIR)/thread-sema.Tpo -c -o thread-sema.lo `test -f 'runtime/thread-sema.c' || echo '$(srcdir)/'`runtime/thread-sema.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/thread-sema.Tpo $(DEPDIR)/thread-sema.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/thread-sema.c' object='thread-sema.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 thread-sema.lo `test -f 'runtime/thread-sema.c' || echo '$(srcdir)/'`runtime/thread-sema.c
+
+lock_futex.lo: runtime/lock_futex.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lock_futex.lo -MD -MP -MF $(DEPDIR)/lock_futex.Tpo -c -o lock_futex.lo `test -f 'runtime/lock_futex.c' || echo '$(srcdir)/'`runtime/lock_futex.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lock_futex.Tpo $(DEPDIR)/lock_futex.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/lock_futex.c' object='lock_futex.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 lock_futex.lo `test -f 'runtime/lock_futex.c' || echo '$(srcdir)/'`runtime/lock_futex.c
+
+thread-linux.lo: runtime/thread-linux.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thread-linux.lo -MD -MP -MF $(DEPDIR)/thread-linux.Tpo -c -o thread-linux.lo `test -f 'runtime/thread-linux.c' || echo '$(srcdir)/'`runtime/thread-linux.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/thread-linux.Tpo $(DEPDIR)/thread-linux.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/thread-linux.c' object='thread-linux.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 thread-linux.lo `test -f 'runtime/thread-linux.c' || echo '$(srcdir)/'`runtime/thread-linux.c
+
mcache.lo: runtime/mcache.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mcache.lo -MD -MP -MF $(DEPDIR)/mcache.Tpo -c -o mcache.lo `test -f 'runtime/mcache.c' || echo '$(srcdir)/'`runtime/mcache.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mcache.Tpo $(DEPDIR)/mcache.Plo
@@ -3217,6 +3196,13 @@ proc.lo: runtime/proc.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 proc.lo `test -f 'runtime/proc.c' || echo '$(srcdir)/'`runtime/proc.c
+runtime.lo: runtime/runtime.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT runtime.lo -MD -MP -MF $(DEPDIR)/runtime.Tpo -c -o runtime.lo `test -f 'runtime/runtime.c' || echo '$(srcdir)/'`runtime/runtime.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/runtime.Tpo $(DEPDIR)/runtime.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/runtime.c' object='runtime.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 runtime.lo `test -f 'runtime/runtime.c' || echo '$(srcdir)/'`runtime/runtime.c
+
thread.lo: runtime/thread.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thread.lo -MD -MP -MF $(DEPDIR)/thread.Tpo -c -o thread.lo `test -f 'runtime/thread.c' || echo '$(srcdir)/'`runtime/thread.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/thread.Tpo $(DEPDIR)/thread.Plo
@@ -4425,6 +4411,14 @@ reflect.c: $(srcdir)/runtime/reflect.goc goc2c
./goc2c --gcc --go-prefix libgo_reflect $< > $@.tmp
mv -f $@.tmp $@
+runtime1.c: $(srcdir)/runtime/runtime1.goc goc2c
+ ./goc2c --gcc --go-prefix libgo_runtime $< > $@.tmp
+ mv -f $@.tmp $@
+
+sema.c: $(srcdir)/runtime/sema.goc goc2c
+ ./goc2c --gcc --go-prefix libgo_runtime $< > $@.tmp
+ mv -f $@.tmp $@
+
sigqueue.c: $(srcdir)/runtime/sigqueue.goc goc2c
./goc2c --gcc --go-prefix libgo_runtime $< > $@.tmp
mv -f $@.tmp $@
diff --git a/libgo/go/syscall/mksyscall.awk b/libgo/go/syscall/mksyscall.awk
index 1b612f3fb99..49828d94ce3 100644
--- a/libgo/go/syscall/mksyscall.awk
+++ b/libgo/go/syscall/mksyscall.awk
@@ -102,10 +102,6 @@ BEGIN {
gofnname, gofnparams, gofnresults == "" ? "" : "(", gofnresults,
gofnresults == "" ? "" : ")", gofnresults == "" ? "" : " ")
- if (blocking) {
- print "\tentersyscall()"
- }
-
loc = gofnname "/" cfnname ":"
split(gofnparams, goargs, ", *")
@@ -151,7 +147,8 @@ BEGIN {
status = 1
next
}
- args = args "StringBytePtr(" goname ")"
+ printf("\t_p%d := StringBytePtr(%s)\n", goarg, goname)
+ args = sprintf("%s_p%d", args, goarg)
} else if (gotype ~ /^\[\](.*)/) {
if (ctype !~ /^\*/ || cargs[carg + 1] == "") {
print loc, "bad C type for slice:", gotype, ctype | "cat 1>&2"
@@ -192,6 +189,10 @@ BEGIN {
next
}
+ if (blocking) {
+ print "\tentersyscall()"
+ }
+
printf("\t")
if (gofnresults != "") {
printf("_r := ")
diff --git a/libgo/runtime/cpuprof.c b/libgo/runtime/cpuprof.c
index bec15ae8ce6..5e3fc99d914 100644
--- a/libgo/runtime/cpuprof.c
+++ b/libgo/runtime/cpuprof.c
@@ -115,12 +115,6 @@ static void add(Profile*, uintptr*, int32);
static bool evict(Profile*, Entry*);
static bool flushlog(Profile*);
-void
-runtime_cpuprofinit(void)
-{
- runtime_initlock(&lk);
-}
-
// LostProfileData is a no-op function used in profiles
// to mark the number of profiling stack traces that were
// discarded due to slow data writers.
@@ -367,9 +361,9 @@ getprofile(Profile *p)
return ret;
// Wait for new log.
- // runtime·entersyscall();
+ runtime_entersyscall();
runtime_notesleep(&p->wait);
- // runtime·exitsyscall();
+ runtime_exitsyscall();
runtime_noteclear(&p->wait);
n = p->handoff;
diff --git a/libgo/runtime/go-close.c b/libgo/runtime/go-close.c
index 778eab3d7d8..a6df3833c26 100644
--- a/libgo/runtime/go-close.c
+++ b/libgo/runtime/go-close.c
@@ -4,6 +4,7 @@
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */
+#include "runtime.h"
#include "go-assert.h"
#include "go-panic.h"
#include "channel.h"
@@ -23,10 +24,7 @@ __go_builtin_close (struct __go_channel *channel)
__go_assert (i == 0);
while (channel->selected_for_send)
- {
- i = pthread_cond_wait (&channel->cond, &channel->lock);
- __go_assert (i == 0);
- }
+ runtime_cond_wait (&channel->cond, &channel->lock);
if (channel->is_closed)
{
diff --git a/libgo/runtime/go-defer.c b/libgo/runtime/go-defer.c
index dda62fb4e1a..c27de6ab463 100644
--- a/libgo/runtime/go-defer.c
+++ b/libgo/runtime/go-defer.c
@@ -16,8 +16,10 @@
void
__go_defer (_Bool *frame, void (*pfn) (void *), void *arg)
{
+ G *g;
struct __go_defer_stack *n;
+ g = runtime_g ();
n = (struct __go_defer_stack *) __go_alloc (sizeof (struct __go_defer_stack));
n->__next = g->defer;
n->__frame = frame;
@@ -33,6 +35,9 @@ __go_defer (_Bool *frame, void (*pfn) (void *), void *arg)
void
__go_undefer (_Bool *frame)
{
+ G *g;
+
+ g = runtime_g ();
while (g->defer != NULL && g->defer->__frame == frame)
{
struct __go_defer_stack *d;
@@ -63,6 +68,9 @@ __go_undefer (_Bool *frame)
_Bool
__go_set_defer_retaddr (void *retaddr)
{
+ G *g;
+
+ g = runtime_g ();
if (g->defer != NULL)
g->defer->__retaddr = retaddr;
return 0;
diff --git a/libgo/runtime/go-deferred-recover.c b/libgo/runtime/go-deferred-recover.c
index d749c2788ab..78ef287cf00 100644
--- a/libgo/runtime/go-deferred-recover.c
+++ b/libgo/runtime/go-deferred-recover.c
@@ -79,6 +79,9 @@
struct __go_empty_interface
__go_deferred_recover ()
{
+ G *g;
+
+ g = runtime_g ();
if (g->defer == NULL || g->defer->__panic != g->panic)
{
struct __go_empty_interface ret;
@@ -87,5 +90,5 @@ __go_deferred_recover ()
ret.__object = NULL;
return ret;
}
- return __go_recover();
+ return __go_recover ();
}
diff --git a/libgo/runtime/go-go.c b/libgo/runtime/go-go.c
deleted file mode 100644
index 82b265f964e..00000000000
--- a/libgo/runtime/go-go.c
+++ /dev/null
@@ -1,668 +0,0 @@
-/* go-go.c -- the go function.
-
- 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. */
-
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <pthread.h>
-#include <semaphore.h>
-
-#include "config.h"
-#include "go-assert.h"
-#include "go-panic.h"
-#include "go-alloc.h"
-#include "runtime.h"
-#include "arch.h"
-#include "malloc.h"
-
-#ifdef USING_SPLIT_STACK
-/* FIXME: This is not declared anywhere. */
-extern void *__splitstack_find (void *, void *, size_t *, void **, void **,
- void **);
-#endif
-
-/* We stop the threads by sending them the signal GO_SIG_STOP and we
- start them by sending them the signal GO_SIG_START. */
-
-#define GO_SIG_START (SIGRTMIN + 1)
-#define GO_SIG_STOP (SIGRTMIN + 2)
-
-#ifndef SA_RESTART
- #define SA_RESTART 0
-#endif
-
-/* A doubly linked list of the threads we have started. */
-
-struct __go_thread_id
-{
- /* Links. */
- struct __go_thread_id *prev;
- struct __go_thread_id *next;
- /* True if the thread ID has not yet been filled in. */
- _Bool tentative;
- /* Thread ID. */
- pthread_t id;
- /* Thread's M structure. */
- struct M *m;
- /* If the thread ID has not been filled in, the function we are
- running. */
- void (*pfn) (void *);
- /* If the thread ID has not been filled in, the argument to the
- function. */
- void *arg;
-};
-
-static struct __go_thread_id *__go_all_thread_ids;
-
-/* A lock to control access to ALL_THREAD_IDS. */
-
-static pthread_mutex_t __go_thread_ids_lock = PTHREAD_MUTEX_INITIALIZER;
-
-/* A semaphore used to wait until all the threads have stopped. */
-
-static sem_t __go_thread_ready_sem;
-
-/* A signal set used to wait until garbage collection is complete. */
-
-static sigset_t __go_thread_wait_sigset;
-
-/* Remove the current thread from the list of threads. */
-
-static void
-remove_current_thread (void *dummy __attribute__ ((unused)))
-{
- struct __go_thread_id *list_entry;
- MCache *mcache;
- int i;
-
- list_entry = m->list_entry;
- mcache = m->mcache;
-
- i = pthread_mutex_lock (&__go_thread_ids_lock);
- __go_assert (i == 0);
-
- if (list_entry->prev != NULL)
- list_entry->prev->next = list_entry->next;
- else
- __go_all_thread_ids = list_entry->next;
- if (list_entry->next != NULL)
- list_entry->next->prev = list_entry->prev;
-
- /* This will lock runtime_mheap as needed. */
- runtime_MCache_ReleaseAll (mcache);
-
- /* This should never deadlock--there shouldn't be any code that
- holds the runtime_mheap lock when locking __go_thread_ids_lock.
- We don't want to do this after releasing __go_thread_ids_lock
- because it will mean that the garbage collector might run, and
- the garbage collector does not try to lock runtime_mheap in all
- cases since it knows it is running single-threaded. */
- runtime_lock (&runtime_mheap);
- mstats.heap_alloc += mcache->local_alloc;
- mstats.heap_objects += mcache->local_objects;
- __builtin_memset (mcache, 0, sizeof (struct MCache));
- runtime_FixAlloc_Free (&runtime_mheap.cachealloc, mcache);
- runtime_unlock (&runtime_mheap);
-
- /* As soon as we release this look, a GC could run. Since this
- thread is no longer on the list, the GC will not find our M
- structure, so it could get freed at any time. That means that
- any code from here to thread exit must not assume that m is
- valid. */
- m = NULL;
- g = NULL;
-
- i = pthread_mutex_unlock (&__go_thread_ids_lock);
- __go_assert (i == 0);
-
- free (list_entry);
-}
-
-/* Start the thread. */
-
-static void *
-start_go_thread (void *thread_arg)
-{
- struct M *newm = (struct M *) thread_arg;
- void (*pfn) (void *);
- void *arg;
- struct __go_thread_id *list_entry;
- int i;
-
-#ifdef __rtems__
- __wrap_rtems_task_variable_add ((void **) &m);
- __wrap_rtems_task_variable_add ((void **) &g);
-#endif
-
- m = newm;
- g = m->curg;
-
- pthread_cleanup_push (remove_current_thread, NULL);
-
- list_entry = newm->list_entry;
-
- pfn = list_entry->pfn;
- arg = list_entry->arg;
-
-#ifndef USING_SPLIT_STACK
- /* If we don't support split stack, record the current stack as the
- top of the stack. There shouldn't be anything relevant to the
- garbage collector above this point. */
- m->gc_sp = (void *) &arg;
-#endif
-
- /* Finish up the entry on the thread list. */
-
- i = pthread_mutex_lock (&__go_thread_ids_lock);
- __go_assert (i == 0);
-
- list_entry->id = pthread_self ();
- list_entry->pfn = NULL;
- list_entry->arg = NULL;
- list_entry->tentative = 0;
-
- i = pthread_mutex_unlock (&__go_thread_ids_lock);
- __go_assert (i == 0);
-
- (*pfn) (arg);
-
- pthread_cleanup_pop (1);
-
- return NULL;
-}
-
-/* The runtime.Goexit function. */
-
-void Goexit (void) asm ("libgo_runtime.runtime.Goexit");
-
-void
-Goexit (void)
-{
- pthread_exit (NULL);
- abort ();
-}
-
-/* Count of threads created. */
-
-static volatile int mcount;
-
-/* Implement the go statement. */
-
-void
-__go_go (void (*pfn) (void*), void *arg)
-{
- int i;
- pthread_attr_t attr;
- struct M *newm;
- struct __go_thread_id *list_entry;
- pthread_t tid;
-
- i = pthread_attr_init (&attr);
- __go_assert (i == 0);
- i = pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
- __go_assert (i == 0);
-
-#ifdef LINKER_SUPPORTS_SPLIT_STACK
- /* The linker knows how to handle calls between code which uses
- -fsplit-stack and code which does not. That means that we can
- run with a smaller stack and rely on the -fsplit-stack support to
- save us. The GNU/Linux glibc library won't let us have a very
- small stack, but we make it as small as we can. */
-#ifndef PTHREAD_STACK_MIN
-#define PTHREAD_STACK_MIN 8192
-#endif
- i = pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
- __go_assert (i == 0);
-#endif
-
- newm = __go_alloc (sizeof (M));
-
- list_entry = malloc (sizeof (struct __go_thread_id));
- list_entry->prev = NULL;
- list_entry->next = NULL;
- list_entry->tentative = 1;
- list_entry->m = newm;
- list_entry->pfn = pfn;
- list_entry->arg = arg;
-
- newm->list_entry = list_entry;
-
- newm->curg = __go_alloc (sizeof (G));
- newm->curg->m = newm;
-
- newm->id = __sync_fetch_and_add (&mcount, 1);
- newm->fastrand = 0x49f6428aUL + newm->id;
-
- newm->mcache = runtime_allocmcache ();
-
- /* Add the thread to the list of all threads, marked as tentative
- since it is not yet ready to go. */
- i = pthread_mutex_lock (&__go_thread_ids_lock);
- __go_assert (i == 0);
-
- if (__go_all_thread_ids != NULL)
- __go_all_thread_ids->prev = list_entry;
- list_entry->next = __go_all_thread_ids;
- __go_all_thread_ids = list_entry;
-
- i = pthread_mutex_unlock (&__go_thread_ids_lock);
- __go_assert (i == 0);
-
- /* Start the thread. */
- i = pthread_create (&tid, &attr, start_go_thread, newm);
- __go_assert (i == 0);
-
- i = pthread_attr_destroy (&attr);
- __go_assert (i == 0);
-}
-
-/* This is the signal handler for GO_SIG_START. The garbage collector
- will send this signal to a thread when it wants the thread to
- start. We don't have to actually do anything here, but we need a
- signal handler since ignoring the signal will mean that the
- sigsuspend will never see it. */
-
-static void
-gc_start_handler (int sig __attribute__ ((unused)))
-{
-}
-
-/* Tell the garbage collector that we are ready, and wait for the
- garbage collector to tell us that it is done. This may be called
- by a signal handler, so it is restricted to using functions which
- are async cancel safe. */
-
-static void
-stop_for_gc (void)
-{
- int i;
-
- /* Tell the garbage collector about our stack. */
-#ifdef USING_SPLIT_STACK
- m->gc_sp = __splitstack_find (NULL, NULL, &m->gc_len,
- &m->gc_next_segment, &m->gc_next_sp,
- &m->gc_initial_sp);
-#else
- {
- uintptr_t top = (uintptr_t) m->gc_sp;
- uintptr_t bottom = (uintptr_t) &top;
- if (top < bottom)
- {
- m->gc_next_sp = m->gc_sp;
- m->gc_len = bottom - top;
- }
- else
- {
- m->gc_next_sp = (void *) bottom;
- m->gc_len = top - bottom;
- }
- }
-#endif
-
- /* Tell the garbage collector that we are ready by posting to the
- semaphore. */
- i = sem_post (&__go_thread_ready_sem);
- __go_assert (i == 0);
-
- /* Wait for the garbage collector to tell us to continue. */
- sigsuspend (&__go_thread_wait_sigset);
-}
-
-/* This is the signal handler for GO_SIG_STOP. The garbage collector
- will send this signal to a thread when it wants the thread to
- stop. */
-
-static void
-gc_stop_handler (int sig __attribute__ ((unused)))
-{
- struct M *pm = m;
-
- if (__sync_bool_compare_and_swap (&pm->holds_finlock, 1, 1))
- {
- /* We can't interrupt the thread while it holds the finalizer
- lock. Otherwise we can get into a deadlock when mark calls
- runtime_walkfintab. */
- __sync_bool_compare_and_swap (&pm->gcing_for_finlock, 0, 1);
- return;
- }
-
- if (__sync_bool_compare_and_swap (&pm->mallocing, 1, 1))
- {
- /* m->mallocing was already non-zero. We can't interrupt the
- thread while it is running an malloc. Instead, tell it to
- call back to us when done. */
- __sync_bool_compare_and_swap (&pm->gcing, 0, 1);
- return;
- }
-
- if (__sync_bool_compare_and_swap (&pm->nomemprof, 1, 1))
- {
- /* Similarly, we can't interrupt the thread while it is building
- profiling information. Otherwise we can get into a deadlock
- when sweepspan calls MProf_Free. */
- __sync_bool_compare_and_swap (&pm->gcing_for_prof, 0, 1);
- return;
- }
-
- stop_for_gc ();
-}
-
-/* This is called by malloc when it gets a signal during the malloc
- call itself. */
-
-int
-__go_run_goroutine_gc (int r)
-{
- /* Force callee-saved registers to be saved on the stack. This is
- not needed if we are invoked from the signal handler, but it is
- needed if we are called directly, since otherwise we might miss
- something that a function somewhere up the call stack is holding
- in a register. */
- __builtin_unwind_init ();
-
- stop_for_gc ();
-
- /* This avoids tail recursion, to make sure that the saved registers
- are on the stack. */
- return r;
-}
-
-/* Stop all the other threads for garbage collection. */
-
-void
-runtime_stoptheworld (void)
-{
- int i;
- pthread_t me;
- int c;
- struct __go_thread_id *p;
-
- i = pthread_mutex_lock (&__go_thread_ids_lock);
- __go_assert (i == 0);
-
- me = pthread_self ();
- c = 0;
- p = __go_all_thread_ids;
- while (p != NULL)
- {
- if (p->tentative || pthread_equal (me, p->id))
- p = p->next;
- else
- {
- i = pthread_kill (p->id, GO_SIG_STOP);
- if (i == 0)
- {
- ++c;
- p = p->next;
- }
- else if (i == ESRCH)
- {
- struct __go_thread_id *next;
-
- /* This thread died somehow. Remove it from the
- list. */
- next = p->next;
- if (p->prev != NULL)
- p->prev->next = next;
- else
- __go_all_thread_ids = next;
- if (next != NULL)
- next->prev = p->prev;
- free (p);
- p = next;
- }
- else
- abort ();
- }
- }
-
- /* Wait for each thread to receive the signal and post to the
- semaphore. If a thread receives the signal but contrives to die
- before it posts to the semaphore, then we will hang forever
- here. */
-
- while (c > 0)
- {
- i = sem_wait (&__go_thread_ready_sem);
- if (i < 0 && errno == EINTR)
- continue;
- __go_assert (i == 0);
- --c;
- }
-
- /* Leave with __go_thread_ids_lock held. */
-}
-
-/* Scan all the stacks for garbage collection. This should be called
- with __go_thread_ids_lock held. */
-
-void
-__go_scanstacks (void (*scan) (byte *, int64))
-{
- pthread_t me;
- struct __go_thread_id *p;
-
- /* Make sure all the registers for this thread are on the stack. */
- __builtin_unwind_init ();
-
- me = pthread_self ();
- for (p = __go_all_thread_ids; p != NULL; p = p->next)
- {
- if (p->tentative)
- {
- /* The goroutine function and argument can be allocated on
- the heap, so we have to scan them for a thread that has
- not yet started. */
- scan ((void *) &p->pfn, sizeof (void *));
- scan ((void *) &p->arg, sizeof (void *));
- scan ((void *) &p->m, sizeof (void *));
- continue;
- }
-
-#ifdef USING_SPLIT_STACK
-
- void *sp;
- size_t len;
- void *next_segment;
- void *next_sp;
- void *initial_sp;
-
- if (pthread_equal (me, p->id))
- {
- next_segment = NULL;
- next_sp = NULL;
- initial_sp = NULL;
- sp = __splitstack_find (NULL, NULL, &len, &next_segment,
- &next_sp, &initial_sp);
- }
- else
- {
- sp = p->m->gc_sp;
- len = p->m->gc_len;
- next_segment = p->m->gc_next_segment;
- next_sp = p->m->gc_next_sp;
- initial_sp = p->m->gc_initial_sp;
- }
-
- while (sp != NULL)
- {
- scan (sp, len);
- sp = __splitstack_find (next_segment, next_sp, &len,
- &next_segment, &next_sp, &initial_sp);
- }
-
-#else /* !defined(USING_SPLIT_STACK) */
-
- if (pthread_equal (me, p->id))
- {
- uintptr_t top = (uintptr_t) m->gc_sp;
- uintptr_t bottom = (uintptr_t) &top;
- if (top < bottom)
- scan (m->gc_sp, bottom - top);
- else
- scan ((void *) bottom, top - bottom);
- }
- else
- {
- scan (p->m->gc_next_sp, p->m->gc_len);
- }
-
-#endif /* !defined(USING_SPLIT_STACK) */
-
- /* Also scan the M structure while we're at it. */
-
- scan ((void *) &p->m, sizeof (void *));
- }
-}
-
-/* Release all the memory caches. This is called with
- __go_thread_ids_lock held. */
-
-void
-__go_stealcache (void)
-{
- struct __go_thread_id *p;
-
- for (p = __go_all_thread_ids; p != NULL; p = p->next)
- runtime_MCache_ReleaseAll (p->m->mcache);
-}
-
-/* Gather memory cache statistics. This is called with
- __go_thread_ids_lock held. */
-
-void
-__go_cachestats (void)
-{
- struct __go_thread_id *p;
-
- for (p = __go_all_thread_ids; p != NULL; p = p->next)
- {
- MCache *c;
- int i;
-
- runtime_purgecachedstats(p->m);
- c = p->m->mcache;
- for (i = 0; i < NumSizeClasses; ++i)
- {
- mstats.by_size[i].nmalloc += c->local_by_size[i].nmalloc;
- c->local_by_size[i].nmalloc = 0;
- mstats.by_size[i].nfree += c->local_by_size[i].nfree;
- c->local_by_size[i].nfree = 0;
- }
- }
-}
-
-/* Start the other threads after garbage collection. */
-
-void
-runtime_starttheworld (bool extra __attribute__ ((unused)))
-{
- int i;
- pthread_t me;
- struct __go_thread_id *p;
-
- /* Here __go_thread_ids_lock should be held. */
-
- me = pthread_self ();
- p = __go_all_thread_ids;
- while (p != NULL)
- {
- if (p->tentative || pthread_equal (me, p->id))
- p = p->next;
- else
- {
- i = pthread_kill (p->id, GO_SIG_START);
- if (i == 0)
- p = p->next;
- else
- abort ();
- }
- }
-
- i = pthread_mutex_unlock (&__go_thread_ids_lock);
- __go_assert (i == 0);
-}
-
-/* Initialize the interaction between goroutines and the garbage
- collector. */
-
-void
-__go_gc_goroutine_init (void *sp __attribute__ ((unused)))
-{
- struct __go_thread_id *list_entry;
- int i;
- sigset_t sset;
- struct sigaction act;
-
- /* Add the initial thread to the list of all threads. */
-
- list_entry = malloc (sizeof (struct __go_thread_id));
- list_entry->prev = NULL;
- list_entry->next = NULL;
- list_entry->tentative = 0;
- list_entry->id = pthread_self ();
- list_entry->m = m;
- list_entry->pfn = NULL;
- list_entry->arg = NULL;
- __go_all_thread_ids = list_entry;
-
- /* Initialize the semaphore which signals when threads are ready for
- GC. */
-
- i = sem_init (&__go_thread_ready_sem, 0, 0);
- __go_assert (i == 0);
-
- /* Fetch the current signal mask. */
-
- i = sigemptyset (&sset);
- __go_assert (i == 0);
- i = sigprocmask (SIG_BLOCK, NULL, &sset);
- __go_assert (i == 0);
-
- /* Make sure that GO_SIG_START is not blocked and GO_SIG_STOP is
- blocked, and save that set for use with later calls to sigsuspend
- while waiting for GC to complete. */
-
- i = sigdelset (&sset, GO_SIG_START);
- __go_assert (i == 0);
- i = sigaddset (&sset, GO_SIG_STOP);
- __go_assert (i == 0);
- __go_thread_wait_sigset = sset;
-
- /* Block SIG_SET_START and unblock SIG_SET_STOP, and use that for
- the process signal mask. */
-
- i = sigaddset (&sset, GO_SIG_START);
- __go_assert (i == 0);
- i = sigdelset (&sset, GO_SIG_STOP);
- __go_assert (i == 0);
- i = sigprocmask (SIG_SETMASK, &sset, NULL);
- __go_assert (i == 0);
-
- /* Install the signal handlers. */
- memset (&act, 0, sizeof act);
- i = sigemptyset (&act.sa_mask);
- __go_assert (i == 0);
-
- act.sa_handler = gc_start_handler;
- act.sa_flags = SA_RESTART;
- i = sigaction (GO_SIG_START, &act, NULL);
- __go_assert (i == 0);
-
- /* We could consider using an alternate signal stack for this. The
- function does not use much stack space, so it may be OK. */
- act.sa_handler = gc_stop_handler;
- i = sigaction (GO_SIG_STOP, &act, NULL);
- __go_assert (i == 0);
-
-#ifndef USING_SPLIT_STACK
- /* If we don't support split stack, record the current stack as the
- top of the stack. */
- m->gc_sp = sp;
-#endif
-}
diff --git a/libgo/runtime/go-gomaxprocs.c b/libgo/runtime/go-gomaxprocs.c
deleted file mode 100644
index 65146c50120..00000000000
--- a/libgo/runtime/go-gomaxprocs.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* go-gomaxprocs.c -- runtime.GOMAXPROCS.
-
- 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 is the runtime.GOMAXPROCS function. This currently does
- nothing, since each goroutine runs in a separate thread anyhow. */
-
-extern int GOMAXPROCS (int) asm ("libgo_runtime.runtime.GOMAXPROCS");
-
-static int set = 1;
-
-int
-GOMAXPROCS (int n)
-{
- int ret;
-
- ret = set;
- if (n > 0)
- set = n;
- return ret;
-}
diff --git a/libgo/runtime/go-lock-os-thread.c b/libgo/runtime/go-lock-os-thread.c
deleted file mode 100644
index 204f11dce7c..00000000000
--- a/libgo/runtime/go-lock-os-thread.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/* go-lock-os-thread.c -- the LockOSThread and UnlockOSThread functions.
-
- 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. */
-
-/* The runtime.LockOSThread and runtime.UnlockOSThread functions are
- meaningless in the current implementation, since for us a goroutine
- always stays on a single OS thread. */
-
-extern void LockOSThread (void) __asm__ ("libgo_runtime.runtime.LockOSThread");
-
-void
-LockOSThread (void)
-{
-}
-
-extern void UnlockOSThread (void)
- __asm__ ("libgo_runtime.runtime.UnlockOSThread");
-
-void
-UnlockOSThread (void)
-{
-}
diff --git a/libgo/runtime/go-main.c b/libgo/runtime/go-main.c
index 15a6a30a93d..8047eaea93f 100644
--- a/libgo/runtime/go-main.c
+++ b/libgo/runtime/go-main.c
@@ -8,6 +8,7 @@
#include <stdlib.h>
#include <time.h>
+#include <unistd.h>
#ifdef HAVE_FPU_CONTROL_H
#include <fpu_control.h>
@@ -15,7 +16,6 @@
#include "go-alloc.h"
#include "array.h"
-#include "go-signal.h"
#include "go-string.h"
#include "runtime.h"
@@ -32,64 +32,43 @@
extern char **environ;
-extern struct __go_open_array Args asm ("libgo_os.os.Args");
-
-extern struct __go_open_array Envs asm ("libgo_os.os.Envs");
-
/* These functions are created for the main package. */
extern void __go_init_main (void);
extern void real_main (void) asm ("main.main");
+static void mainstart (void *);
+
/* The main function. */
int
main (int argc, char **argv)
{
- int i;
- struct __go_string *values;
-
- m = &runtime_m0;
- g = &runtime_g0;
- m->curg = g;
- g->m = m;
- runtime_mallocinit ();
- runtime_cpuprofinit ();
- __go_gc_goroutine_init (&argc);
-
- Args.__count = argc;
- Args.__capacity = argc;
- values = __go_alloc (argc * sizeof (struct __go_string));
- for (i = 0; i < argc; ++i)
- {
- values[i].__data = (unsigned char *) argv[i];
- values[i].__length = __builtin_strlen (argv[i]);
- }
- Args.__values = values;
-
- for (i = 0; environ[i] != NULL; ++i)
- ;
- Envs.__count = i;
- Envs.__capacity = i;
- values = __go_alloc (i * sizeof (struct __go_string));
- for (i = 0; environ[i] != NULL; ++i)
- {
- values[i].__data = (unsigned char *) environ[i];
- values[i].__length = __builtin_strlen (environ[i]);
- }
- Envs.__values = values;
-
- __initsig ();
+ runtime_initsig (0);
+ runtime_args (argc, (byte **) argv);
+ runtime_osinit ();
+ runtime_schedinit ();
#if defined(HAVE_SRANDOM)
srandom ((unsigned int) time (NULL));
#else
srand ((unsigned int) time (NULL));
#endif
+
+ __go_go (mainstart, NULL);
+ runtime_mstart (runtime_m ());
+ abort ();
+}
+
+static void
+mainstart (void *arg __attribute__ ((unused)))
+{
__go_init_main ();
- __go_enable_gc ();
+ mstats.enablegc = 1;
real_main ();
- return 0;
+ runtime_exit (0);
+
+ abort ();
}
diff --git a/libgo/runtime/go-nanotime.c b/libgo/runtime/go-nanotime.c
index 8cd42301054..197fb15d2a5 100644
--- a/libgo/runtime/go-nanotime.c
+++ b/libgo/runtime/go-nanotime.c
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Return time in nanoseconds. This is only used for computing runtime.
+// Return current time in nanoseconds.
#include <sys/time.h>
diff --git a/libgo/runtime/go-note.c b/libgo/runtime/go-note.c
deleted file mode 100644
index 62c229fa0d9..00000000000
--- a/libgo/runtime/go-note.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/* go-note.c -- implement notesleep, notewakeup and noteclear.
-
- 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. */
-
-/* A note is a one-time notification. noteclear clears the note.
- notesleep waits for a call to notewakeup. notewakeup wakes up
- every thread waiting on the note. */
-
-#include "go-assert.h"
-#include "runtime.h"
-
-/* We use a single global lock and condition variable. It would be
- 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;
-
-/* noteclear is called before any calls to notesleep or
- notewakeup. */
-
-void
-runtime_noteclear (Note* n)
-{
- int32 i;
-
- i = pthread_mutex_lock (&note_lock);
- __go_assert (i == 0);
-
- n->woken = 0;
-
- i = pthread_mutex_unlock (&note_lock);
- __go_assert (i == 0);
-}
-
-/* Wait until notewakeup is called. */
-
-void
-runtime_notesleep (Note* n)
-{
- int32 i;
-
- i = pthread_mutex_lock (&note_lock);
- __go_assert (i == 0);
-
- while (!n->woken)
- {
- i = pthread_cond_wait (&note_cond, &note_lock);
- __go_assert (i == 0);
- }
-
- i = pthread_mutex_unlock (&note_lock);
- __go_assert (i == 0);
-}
-
-/* Wake up every thread sleeping on the note. */
-
-void
-runtime_notewakeup (Note *n)
-{
- int32 i;
-
- i = pthread_mutex_lock (&note_lock);
- __go_assert (i == 0);
-
- n->woken = 1;
-
- i = pthread_cond_broadcast (&note_cond);
- __go_assert (i == 0);
-
- i = pthread_mutex_unlock (&note_lock);
- __go_assert (i == 0);
-}
diff --git a/libgo/runtime/go-panic.c b/libgo/runtime/go-panic.c
index 8b95cd4e4d1..23df57930b7 100644
--- a/libgo/runtime/go-panic.c
+++ b/libgo/runtime/go-panic.c
@@ -39,8 +39,11 @@ __printpanics (struct __go_panic_stack *p)
void
__go_panic (struct __go_empty_interface arg)
{
+ G *g;
struct __go_panic_stack *n;
+ g = runtime_g ();
+
n = (struct __go_panic_stack *) __go_alloc (sizeof (struct __go_panic_stack));
n->__arg = arg;
n->__next = g->panic;
@@ -98,10 +101,9 @@ __go_panic (struct __go_empty_interface arg)
/* The panic was not recovered. */
+ runtime_startpanic ();
__printpanics (g->panic);
-
- /* FIXME: We should dump a call stack here. */
- abort ();
+ runtime_dopanic (0);
}
/* This is used by the runtime library. */
diff --git a/libgo/runtime/go-rand.c b/libgo/runtime/go-rand.c
deleted file mode 100644
index 9632efc09cd..00000000000
--- a/libgo/runtime/go-rand.c
+++ /dev/null
@@ -1,18 +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.
-
-#include "runtime.h"
-
-uint32
-runtime_fastrand1(void)
-{
- uint32 x;
-
- x = m->fastrand;
- x += x;
- if(x & 0x80000000L)
- x ^= 0x88888eefUL;
- m->fastrand = x;
- return x;
-}
diff --git a/libgo/runtime/go-rec-nb-small.c b/libgo/runtime/go-rec-nb-small.c
index 054392009c3..c21878ce131 100644
--- a/libgo/runtime/go-rec-nb-small.c
+++ b/libgo/runtime/go-rec-nb-small.c
@@ -6,6 +6,7 @@
#include <stdint.h>
+#include "runtime.h"
#include "go-assert.h"
#include "go-panic.h"
#include "channel.h"
@@ -22,10 +23,7 @@ __go_receive_nonblocking_acquire (struct __go_channel *channel)
__go_assert (i == 0);
while (channel->selected_for_receive)
- {
- i = pthread_cond_wait (&channel->cond, &channel->lock);
- __go_assert (i == 0);
- }
+ runtime_cond_wait (&channel->cond, &channel->lock);
if (channel->is_closed
&& (channel->num_entries == 0
@@ -59,10 +57,7 @@ __go_receive_nonblocking_acquire (struct __go_channel *channel)
__go_broadcast_to_select (channel);
while (channel->next_store == 0)
- {
- i = pthread_cond_wait (&channel->cond, &channel->lock);
- __go_assert (i == 0);
- }
+ runtime_cond_wait (&channel->cond, &channel->lock);
has_data = 1;
}
diff --git a/libgo/runtime/go-rec-small.c b/libgo/runtime/go-rec-small.c
index d9476329694..f26dbcdd993 100644
--- a/libgo/runtime/go-rec-small.c
+++ b/libgo/runtime/go-rec-small.c
@@ -6,6 +6,7 @@
#include <stdint.h>
+#include "runtime.h"
#include "go-assert.h"
#include "go-panic.h"
#include "channel.h"
@@ -198,8 +199,7 @@ __go_receive_acquire (struct __go_channel *channel, _Bool for_select)
/* Wait for something to change, then loop around and try
again. */
- i = pthread_cond_wait (&channel->cond, &channel->lock);
- __go_assert (i == 0);
+ runtime_cond_wait (&channel->cond, &channel->lock);
}
}
diff --git a/libgo/runtime/go-recover.c b/libgo/runtime/go-recover.c
index fe6031c100f..7101d518ade 100644
--- a/libgo/runtime/go-recover.c
+++ b/libgo/runtime/go-recover.c
@@ -18,10 +18,13 @@
_Bool
__go_can_recover (const void* retaddr)
{
+ G *g;
struct __go_defer_stack *d;
const char* ret;
const char* dret;
+ g = runtime_g ();
+
d = g->defer;
if (d == NULL)
return 0;
@@ -50,8 +53,11 @@ __go_can_recover (const void* retaddr)
struct __go_empty_interface
__go_recover ()
{
+ G *g;
struct __go_panic_stack *p;
+ g = runtime_g ();
+
if (g->panic == NULL || g->panic->__was_recovered)
{
struct __go_empty_interface ret;
diff --git a/libgo/runtime/go-sched.c b/libgo/runtime/go-sched.c
deleted file mode 100644
index 2e36d31a5dc..00000000000
--- a/libgo/runtime/go-sched.c
+++ /dev/null
@@ -1,15 +0,0 @@
-/* go-sched.c -- the runtime.Gosched function.
-
- 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. */
-
-#include <sched.h>
-
-void Gosched (void) asm ("libgo_runtime.runtime.Gosched");
-
-void
-Gosched (void)
-{
- sched_yield ();
-}
diff --git a/libgo/runtime/go-select.c b/libgo/runtime/go-select.c
index e425aae24c7..677c699b52c 100644
--- a/libgo/runtime/go-select.c
+++ b/libgo/runtime/go-select.c
@@ -11,6 +11,7 @@
#include <stdlib.h>
#include <unistd.h>
+#include "runtime.h"
#include "config.h"
#include "go-assert.h"
#include "channel.h"
@@ -746,10 +747,7 @@ __go_select (uintptr_t count, _Bool has_default,
(is_queued
? NULL
: &selected_for_read)))
- {
- x = pthread_cond_wait (&__go_select_cond, &__go_select_mutex);
- __go_assert (x == 0);
- }
+ runtime_cond_wait (&__go_select_cond, &__go_select_mutex);
is_queued = 1;
}
diff --git a/libgo/runtime/go-semacquire.c b/libgo/runtime/go-semacquire.c
deleted file mode 100644
index 05b637776da..00000000000
--- a/libgo/runtime/go-semacquire.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/* go-semacquire.c -- implement runtime.Semacquire and runtime.Semrelease.
-
- 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. */
-
-#include <stdint.h>
-
-#include <pthread.h>
-
-#include "go-assert.h"
-#include "runtime.h"
-
-/* 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 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;
-
-/* If the value in *ADDR is positive, and we are able to atomically
- decrement it, return true. Otherwise do nothing and return
- false. */
-
-static _Bool
-acquire (uint32 *addr)
-{
- while (1)
- {
- uint32 val;
-
- val = *addr;
- if (val == 0)
- return 0;
- if (__sync_bool_compare_and_swap (addr, val, val - 1))
- return 1;
- }
-}
-
-/* Implement runtime.Semacquire. ADDR points to a semaphore count.
- We have acquired the semaphore when we have decremented the count
- and it remains nonnegative. */
-
-void
-runtime_semacquire (uint32 *addr)
-{
- while (1)
- {
- int i;
-
- /* If the current count is positive, and we are able to atomically
- decrement it, then we have acquired the semaphore. */
- if (acquire (addr))
- return;
-
- /* Lock the mutex. */
- i = pthread_mutex_lock (&sem_lock);
- __go_assert (i == 0);
-
- /* Check the count again with the mutex locked. */
- if (acquire (addr))
- {
- i = pthread_mutex_unlock (&sem_lock);
- __go_assert (i == 0);
- return;
- }
-
- /* The count is zero. Even if a call to runtime.Semrelease
- increments it to become positive, that call will try to
- acquire the mutex and block, so we are sure to see the signal
- of the condition variable. */
- i = pthread_cond_wait (&sem_cond, &sem_lock);
- __go_assert (i == 0);
-
- /* Unlock the mutex and try again. */
- i = pthread_mutex_unlock (&sem_lock);
- __go_assert (i == 0);
- }
-}
-
-/* Implement runtime.Semrelease. ADDR points to a semaphore count. We
- must atomically increment the count. If the count becomes
- positive, we signal the condition variable to wake up another
- process. */
-
-void
-runtime_semrelease (uint32 *addr)
-{
- int32_t val;
-
- val = __sync_fetch_and_add (addr, 1);
-
- /* VAL is the old value. It should never be negative. If it is
- negative, that implies that Semacquire somehow decremented a zero
- value, or that the count has overflowed. */
- __go_assert (val >= 0);
-
- /* If the old value was zero, then we have now released a count, and
- we signal the condition variable. If the old value was positive,
- then nobody can be waiting. We have to use
- pthread_cond_broadcast, not pthread_cond_signal, because
- otherwise there would be a race condition when the count is
- incremented twice before any locker manages to decrement it. */
- if (val == 0)
- {
- int i;
-
- i = pthread_mutex_lock (&sem_lock);
- __go_assert (i == 0);
-
- i = pthread_cond_broadcast (&sem_cond);
- __go_assert (i == 0);
-
- i = pthread_mutex_unlock (&sem_lock);
- __go_assert (i == 0);
- }
-}
-
-
-#ifndef HAVE_SYNC_FETCH_AND_ADD_4
-
-/* For targets which don't have the required sync support. Really
- this should be provided by gcc itself. FIXME. */
-
-static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER;
-
-uint32
-__sync_fetch_and_add_4(uint32*, uint32)
- __attribute__((visibility("hidden")));
-
-uint32
-__sync_fetch_and_add_4(uint32* ptr, uint32 add)
-{
- int i;
- uint32 ret;
-
- i = pthread_mutex_lock(&sync_lock);
- __go_assert(i == 0);
-
- ret = *ptr;
- *ptr += add;
-
- i = pthread_mutex_unlock(&sync_lock);
- __go_assert(i == 0);
-
- return ret;
-}
-
-#endif
diff --git a/libgo/runtime/go-send-nb-small.c b/libgo/runtime/go-send-nb-small.c
index 51914dbfa3c..f3336099bf7 100644
--- a/libgo/runtime/go-send-nb-small.c
+++ b/libgo/runtime/go-send-nb-small.c
@@ -6,6 +6,7 @@
#include <stdint.h>
+#include "runtime.h"
#include "go-assert.h"
#include "go-panic.h"
#include "channel.h"
@@ -24,10 +25,7 @@ __go_send_nonblocking_acquire (struct __go_channel *channel)
__go_assert (i == 0);
while (channel->selected_for_send)
- {
- i = pthread_cond_wait (&channel->cond, &channel->lock);
- __go_assert (i == 0);
- }
+ runtime_cond_wait (&channel->cond, &channel->lock);
if (channel->is_closed)
{
diff --git a/libgo/runtime/go-send-small.c b/libgo/runtime/go-send-small.c
index 25e3c82bd89..89a7032756d 100644
--- a/libgo/runtime/go-send-small.c
+++ b/libgo/runtime/go-send-small.c
@@ -6,6 +6,7 @@
#include <stdint.h>
+#include "runtime.h"
#include "go-assert.h"
#include "go-panic.h"
#include "channel.h"
@@ -62,8 +63,7 @@ __go_send_acquire (struct __go_channel *channel, _Bool for_select)
/* Wait for something to change, then loop around and try
again. */
- i = pthread_cond_wait (&channel->cond, &channel->lock);
- __go_assert (i == 0);
+ runtime_cond_wait (&channel->cond, &channel->lock);
}
}
@@ -118,8 +118,7 @@ __go_send_release (struct __go_channel *channel)
}
}
- i = pthread_cond_wait (&channel->cond, &channel->lock);
- __go_assert (i == 0);
+ runtime_cond_wait (&channel->cond, &channel->lock);
}
channel->waiting_to_send = 0;
diff --git a/libgo/runtime/go-signal.c b/libgo/runtime/go-signal.c
index c16b058b79e..468235ddf4e 100644
--- a/libgo/runtime/go-signal.c
+++ b/libgo/runtime/go-signal.c
@@ -6,13 +6,12 @@
#include <signal.h>
#include <stdlib.h>
+#include <unistd.h>
#include <sys/time.h>
+#include "runtime.h"
#include "go-assert.h"
#include "go-panic.h"
-#include "go-signal.h"
-
-#include "runtime.h"
#ifndef SA_RESTART
#define SA_RESTART 0
@@ -24,6 +23,10 @@ struct sigtab
{
/* Signal number. */
int sig;
+ /* Nonzero if the signal should be caught. */
+ _Bool catch;
+ /* Nonzero if the signal should be queued. */
+ _Bool queue;
/* Nonzero if the signal should be ignored. */
_Bool ignore;
/* Nonzero if we should restart system calls. */
@@ -34,62 +37,81 @@ struct sigtab
static struct sigtab signals[] =
{
- { SIGHUP, 0, 1 },
- { SIGINT, 0, 1 },
- { SIGALRM, 1, 1 },
- { SIGTERM, 0, 1 },
+ { SIGHUP, 0, 1, 0, 1 },
+ { SIGINT, 0, 1, 0, 1 },
+ { SIGQUIT, 0, 1, 0, 1 },
+ { SIGALRM, 0, 1, 1, 1 },
+ { SIGTERM, 0, 1, 0, 1 },
+#ifdef SIGILL
+ { SIGILL, 1, 0, 0, 0 },
+#endif
+#ifdef SIGTRAP
+ { SIGTRAP, 1, 0, 0, 0 },
+#endif
+#ifdef SIGABRT
+ { SIGABRT, 1, 0, 0, 0 },
+#endif
#ifdef SIGBUS
- { SIGBUS, 0, 0 },
+ { SIGBUS, 1, 0, 0, 0 },
#endif
#ifdef SIGFPE
- { SIGFPE, 0, 0 },
+ { SIGFPE, 1, 0, 0, 0 },
#endif
#ifdef SIGUSR1
- { SIGUSR1, 1, 1 },
+ { SIGUSR1, 0, 1, 1, 1 },
#endif
#ifdef SIGSEGV
- { SIGSEGV, 0, 0 },
+ { SIGSEGV, 1, 0, 0, 0 },
#endif
#ifdef SIGUSR2
- { SIGUSR2, 1, 1 },
+ { SIGUSR2, 0, 1, 1, 1 },
#endif
#ifdef SIGPIPE
- { SIGPIPE, 1, 0 },
+ { SIGPIPE, 0, 0, 1, 0 },
+#endif
+#ifdef SIGSTKFLT
+ { SIGSTKFLT, 1, 0, 0, 0 },
#endif
#ifdef SIGCHLD
- { SIGCHLD, 1, 1 },
+ { SIGCHLD, 0, 1, 1, 1 },
#endif
#ifdef SIGTSTP
- { SIGTSTP, 1, 1 },
+ { SIGTSTP, 0, 1, 1, 1 },
#endif
#ifdef SIGTTIN
- { SIGTTIN, 1, 1 },
+ { SIGTTIN, 0, 1, 1, 1 },
#endif
#ifdef SIGTTOU
- { SIGTTOU, 1, 1 },
+ { SIGTTOU, 0, 1, 1, 1 },
#endif
#ifdef SIGURG
- { SIGURG, 1, 1 },
+ { SIGURG, 0, 1, 1, 1 },
#endif
#ifdef SIGXCPU
- { SIGXCPU, 1, 1 },
+ { SIGXCPU, 0, 1, 1, 1 },
#endif
#ifdef SIGXFSZ
- { SIGXFSZ, 1, 1 },
+ { SIGXFSZ, 0, 1, 1, 1 },
#endif
#ifdef SIGVTARLM
- { SIGVTALRM, 1, 1 },
+ { SIGVTALRM, 0, 1, 1, 1 },
+#endif
+#ifdef SIGPROF
+ { SIGPROF, 0, 1, 1, 1 },
#endif
#ifdef SIGWINCH
- { SIGWINCH, 1, 1 },
+ { SIGWINCH, 0, 1, 1, 1 },
#endif
#ifdef SIGIO
- { SIGIO, 1, 1 },
+ { SIGIO, 0, 1, 1, 1 },
#endif
#ifdef SIGPWR
- { SIGPWR, 1, 1 },
+ { SIGPWR, 0, 1, 1, 1 },
+#endif
+#ifdef SIGSYS
+ { SIGSYS, 1, 0, 0, 0 },
#endif
- { -1, 0, 0 }
+ { -1, 0, 0, 0, 0 }
};
/* The Go signal handler. */
@@ -103,7 +125,7 @@ sighandler (int sig)
if (sig == SIGPROF)
{
/* FIXME. */
- runtime_sigprof (0, 0, nil);
+ runtime_sigprof (0, 0, nil, nil);
return;
}
@@ -112,6 +134,12 @@ sighandler (int sig)
msg = NULL;
switch (sig)
{
+#ifdef SIGILL
+ case SIGILL:
+ msg = "illegal instruction";
+ break;
+#endif
+
#ifdef SIGBUS
case SIGBUS:
msg = "invalid memory address or nil pointer dereference";
@@ -138,7 +166,7 @@ sighandler (int sig)
{
sigset_t clear;
- if (__sync_bool_compare_and_swap (&m->mallocing, 1, 1))
+ if (runtime_m()->mallocing)
{
fprintf (stderr, "caught signal while mallocing: %s\n", msg);
__go_assert (0);
@@ -153,16 +181,22 @@ sighandler (int sig)
__go_panic_msg (msg);
}
- if (__go_sigsend (sig))
- return;
for (i = 0; signals[i].sig != -1; ++i)
{
if (signals[i].sig == sig)
{
struct sigaction sa;
- if (signals[i].ignore)
- return;
+ if (signals[i].queue)
+ {
+ if (__go_sigsend (sig) || signals[i].ignore)
+ return;
+ runtime_exit (2); // SIGINT, SIGTERM, etc
+ }
+
+ if (runtime_panicking)
+ runtime_exit (2);
+ runtime_panicking = 1;
memset (&sa, 0, sizeof sa);
@@ -181,11 +215,18 @@ sighandler (int sig)
abort ();
}
+/* Ignore a signal. */
+
+static void
+sigignore (int sig __attribute__ ((unused)))
+{
+}
+
/* Initialize signal handling for Go. This is called when the program
starts. */
void
-__initsig ()
+runtime_initsig (int32 queue)
{
struct sigaction sa;
int i;
@@ -201,6 +242,12 @@ __initsig ()
for (i = 0; signals[i].sig != -1; ++i)
{
+ if (signals[i].queue != (queue ? 1 : 0))
+ continue;
+ if (signals[i].catch || signals[i].queue)
+ sa.sa_handler = sighandler;
+ else
+ sa.sa_handler = sigignore;
sa.sa_flags = signals[i].restart ? SA_RESTART : 0;
if (sigaction (signals[i].sig, &sa, NULL) != 0)
__go_assert (0);
@@ -243,7 +290,7 @@ runtime_resetcpuprofiler(int32 hz)
__go_assert (i == 0);
}
- m->profilehz = hz;
+ runtime_m()->profilehz = hz;
}
/* Used by the os package to raise SIGPIPE. */
diff --git a/libgo/runtime/go-signal.h b/libgo/runtime/go-signal.h
deleted file mode 100644
index a30173a34de..00000000000
--- a/libgo/runtime/go-signal.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/* go-signal.h -- signal handling for Go.
-
- 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. */
-
-extern void __initsig (void);
diff --git a/libgo/runtime/go-unwind.c b/libgo/runtime/go-unwind.c
index 58c675a2dc8..c669a3ce889 100644
--- a/libgo/runtime/go-unwind.c
+++ b/libgo/runtime/go-unwind.c
@@ -47,8 +47,11 @@ static const _Unwind_Exception_Class __go_exception_class =
void
__go_check_defer (_Bool *frame)
{
+ G *g;
struct _Unwind_Exception *hdr;
+ g = runtime_g ();
+
if (g == NULL)
{
/* Some other language has thrown an exception. We know there
@@ -164,7 +167,7 @@ __go_unwind_stack ()
sizeof hdr->exception_class);
hdr->exception_cleanup = NULL;
- g->exception = hdr;
+ runtime_g ()->exception = hdr;
#ifdef __USING_SJLJ_EXCEPTIONS__
_Unwind_SjLj_RaiseException (hdr);
@@ -280,6 +283,7 @@ PERSONALITY_FUNCTION (int version,
_Unwind_Ptr landing_pad, ip;
int ip_before_insn = 0;
_Bool is_foreign;
+ G *g;
#ifdef __ARM_EABI_UNWINDER__
_Unwind_Action actions;
@@ -416,6 +420,7 @@ PERSONALITY_FUNCTION (int version,
/* It's possible for g to be NULL here for an exception thrown by a
language other than Go. */
+ g = runtime_g ();
if (g == NULL)
{
if (!is_foreign)
diff --git a/libgo/runtime/lock_futex.c b/libgo/runtime/lock_futex.c
new file mode 100644
index 00000000000..4f3d507726d
--- /dev/null
+++ b/libgo/runtime/lock_futex.c
@@ -0,0 +1,146 @@
+// 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.
+
+#include "runtime.h"
+
+// This implementation depends on OS-specific implementations of
+//
+// runtime.futexsleep(uint32 *addr, uint32 val, int64 ns)
+// Atomically,
+// if(*addr == val) sleep
+// Might be woken up spuriously; that's allowed.
+// Don't sleep longer than ns; ns < 0 means forever.
+//
+// runtime.futexwakeup(uint32 *addr, uint32 cnt)
+// If any procs are sleeping on addr, wake up at most cnt.
+
+enum
+{
+ MUTEX_UNLOCKED = 0,
+ MUTEX_LOCKED = 1,
+ MUTEX_SLEEPING = 2,
+
+ ACTIVE_SPIN = 4,
+ ACTIVE_SPIN_CNT = 30,
+ PASSIVE_SPIN = 1,
+};
+
+// Possible lock states are MUTEX_UNLOCKED, MUTEX_LOCKED and MUTEX_SLEEPING.
+// MUTEX_SLEEPING means that there is presumably at least one sleeping thread.
+// Note that there can be spinning threads during all states - they do not
+// affect mutex's state.
+void
+runtime_lock(Lock *l)
+{
+ uint32 i, v, wait, spin;
+
+ if(runtime_m()->locks++ < 0)
+ runtime_throw("runtime_lock: lock count");
+
+ // Speculative grab for lock.
+ v = runtime_xchg(&l->key, MUTEX_LOCKED);
+ if(v == MUTEX_UNLOCKED)
+ return;
+
+ // wait is either MUTEX_LOCKED or MUTEX_SLEEPING
+ // depending on whether there is a thread sleeping
+ // on this mutex. If we ever change l->key from
+ // MUTEX_SLEEPING to some other value, we must be
+ // careful to change it back to MUTEX_SLEEPING before
+ // returning, to ensure that the sleeping thread gets
+ // its wakeup call.
+ wait = v;
+
+ // On uniprocessor's, no point spinning.
+ // On multiprocessors, spin for ACTIVE_SPIN attempts.
+ spin = 0;
+ if(runtime_ncpu > 1)
+ spin = ACTIVE_SPIN;
+
+ for(;;) {
+ // Try for lock, spinning.
+ for(i = 0; i < spin; i++) {
+ while(l->key == MUTEX_UNLOCKED)
+ if(runtime_cas(&l->key, MUTEX_UNLOCKED, wait))
+ return;
+ runtime_procyield(ACTIVE_SPIN_CNT);
+ }
+
+ // Try for lock, rescheduling.
+ for(i=0; i < PASSIVE_SPIN; i++) {
+ while(l->key == MUTEX_UNLOCKED)
+ if(runtime_cas(&l->key, MUTEX_UNLOCKED, wait))
+ return;
+ runtime_osyield();
+ }
+
+ // Sleep.
+ v = runtime_xchg(&l->key, MUTEX_SLEEPING);
+ if(v == MUTEX_UNLOCKED)
+ return;
+ wait = MUTEX_SLEEPING;
+ runtime_futexsleep(&l->key, MUTEX_SLEEPING, -1);
+ }
+}
+
+void
+runtime_unlock(Lock *l)
+{
+ uint32 v;
+
+ if(--runtime_m()->locks < 0)
+ runtime_throw("runtime_unlock: lock count");
+
+ v = runtime_xchg(&l->key, MUTEX_UNLOCKED);
+ if(v == MUTEX_UNLOCKED)
+ runtime_throw("unlock of unlocked lock");
+ if(v == MUTEX_SLEEPING)
+ runtime_futexwakeup(&l->key, 1);
+}
+
+// One-time notifications.
+void
+runtime_noteclear(Note *n)
+{
+ n->key = 0;
+}
+
+void
+runtime_notewakeup(Note *n)
+{
+ runtime_xchg(&n->key, 1);
+ runtime_futexwakeup(&n->key, 1);
+}
+
+void
+runtime_notesleep(Note *n)
+{
+ while(runtime_atomicload(&n->key) == 0)
+ runtime_futexsleep(&n->key, 0, -1);
+}
+
+void
+runtime_notetsleep(Note *n, int64 ns)
+{
+ int64 deadline, now;
+
+ if(ns < 0) {
+ runtime_notesleep(n);
+ return;
+ }
+
+ if(runtime_atomicload(&n->key) != 0)
+ return;
+
+ deadline = runtime_nanotime() + ns;
+ for(;;) {
+ runtime_futexsleep(&n->key, 0, ns);
+ if(runtime_atomicload(&n->key) != 0)
+ return;
+ now = runtime_nanotime();
+ if(now >= deadline)
+ return;
+ ns = deadline - now;
+ }
+}
diff --git a/libgo/runtime/lock_sema.c b/libgo/runtime/lock_sema.c
new file mode 100644
index 00000000000..2fa837d8b0e
--- /dev/null
+++ b/libgo/runtime/lock_sema.c
@@ -0,0 +1,217 @@
+// 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.
+
+#include "runtime.h"
+
+// This implementation depends on OS-specific implementations of
+//
+// uintptr runtime.semacreate(void)
+// Create a semaphore, which will be assigned to m->waitsema.
+// The zero value is treated as absence of any semaphore,
+// so be sure to return a non-zero value.
+//
+// int32 runtime.semasleep(int64 ns)
+// If ns < 0, acquire m->waitsema and return 0.
+// If ns >= 0, try to acquire m->waitsema for at most ns nanoseconds.
+// Return 0 if the semaphore was acquired, -1 if interrupted or timed out.
+//
+// int32 runtime.semawakeup(M *mp)
+// Wake up mp, which is or will soon be sleeping on mp->waitsema.
+//
+
+enum
+{
+ LOCKED = 1,
+
+ ACTIVE_SPIN = 4,
+ ACTIVE_SPIN_CNT = 30,
+ PASSIVE_SPIN = 1,
+};
+
+void
+runtime_lock(Lock *l)
+{
+ uintptr v;
+ uint32 i, spin;
+
+ if(m->locks++ < 0)
+ runtime_throw("runtime_lock: lock count");
+
+ // Speculative grab for lock.
+ if(runtime_casp(&l->waitm, nil, (void*)LOCKED))
+ return;
+
+ if(m->waitsema == 0)
+ m->waitsema = runtime_semacreate();
+
+ // On uniprocessor's, no point spinning.
+ // On multiprocessors, spin for ACTIVE_SPIN attempts.
+ spin = 0;
+ if(runtime_ncpu > 1)
+ spin = ACTIVE_SPIN;
+
+ for(i=0;; i++) {
+ v = (uintptr)runtime_atomicloadp(&l->waitm);
+ if((v&LOCKED) == 0) {
+unlocked:
+ if(runtime_casp(&l->waitm, (void*)v, (void*)(v|LOCKED)))
+ return;
+ i = 0;
+ }
+ if(i<spin)
+ runtime_procyield(ACTIVE_SPIN_CNT);
+ else if(i<spin+PASSIVE_SPIN)
+ runtime_osyield();
+ else {
+ // Someone else has it.
+ // l->waitm points to a linked list of M's waiting
+ // for this lock, chained through m->nextwaitm.
+ // Queue this M.
+ for(;;) {
+ m->nextwaitm = (void*)(v&~LOCKED);
+ if(runtime_casp(&l->waitm, (void*)v, (void*)((uintptr)m|LOCKED)))
+ break;
+ v = (uintptr)runtime_atomicloadp(&l->waitm);
+ if((v&LOCKED) == 0)
+ goto unlocked;
+ }
+ if(v&LOCKED) {
+ // Queued. Wait.
+ runtime_semasleep(-1);
+ i = 0;
+ }
+ }
+ }
+}
+
+void
+runtime_unlock(Lock *l)
+{
+ uintptr v;
+ M *mp;
+
+ if(--m->locks < 0)
+ runtime_throw("runtime_unlock: lock count");
+
+ for(;;) {
+ v = (uintptr)runtime_atomicloadp(&l->waitm);
+ if(v == LOCKED) {
+ if(runtime_casp(&l->waitm, (void*)LOCKED, nil))
+ break;
+ } else {
+ // Other M's are waiting for the lock.
+ // Dequeue an M.
+ mp = (void*)(v&~LOCKED);
+ if(runtime_casp(&l->waitm, (void*)v, mp->nextwaitm)) {
+ // Dequeued an M. Wake it.
+ runtime_semawakeup(mp);
+ break;
+ }
+ }
+ }
+}
+
+// One-time notifications.
+void
+runtime_noteclear(Note *n)
+{
+ n->waitm = nil;
+}
+
+void
+runtime_notewakeup(Note *n)
+{
+ M *mp;
+
+ do
+ mp = runtime_atomicloadp(&n->waitm);
+ while(!runtime_casp(&n->waitm, mp, (void*)LOCKED));
+
+ // Successfully set waitm to LOCKED.
+ // What was it before?
+ if(mp == nil) {
+ // Nothing was waiting. Done.
+ } else if(mp == (M*)LOCKED) {
+ // Two notewakeups! Not allowed.
+ runtime_throw("notewakeup - double wakeup");
+ } else {
+ // Must be the waiting m. Wake it up.
+ runtime_semawakeup(mp);
+ }
+}
+
+void
+runtime_notesleep(Note *n)
+{
+ if(m->waitsema == 0)
+ m->waitsema = runtime_semacreate();
+ if(!runtime_casp(&n->waitm, nil, m)) { // must be LOCKED (got wakeup)
+ if(n->waitm != (void*)LOCKED)
+ runtime_throw("notesleep - waitm out of sync");
+ return;
+ }
+ // Queued. Sleep.
+ runtime_semasleep(-1);
+}
+
+void
+runtime_notetsleep(Note *n, int64 ns)
+{
+ M *mp;
+ int64 deadline, now;
+
+ if(ns < 0) {
+ runtime_notesleep(n);
+ return;
+ }
+
+ if(m->waitsema == 0)
+ m->waitsema = runtime_semacreate();
+
+ // Register for wakeup on n->waitm.
+ if(!runtime_casp(&n->waitm, nil, m)) { // must be LOCKED (got wakeup already)
+ if(n->waitm != (void*)LOCKED)
+ runtime_throw("notetsleep - waitm out of sync");
+ return;
+ }
+
+ deadline = runtime_nanotime() + ns;
+ for(;;) {
+ // Registered. Sleep.
+ if(runtime_semasleep(ns) >= 0) {
+ // Acquired semaphore, semawakeup unregistered us.
+ // Done.
+ return;
+ }
+
+ // Interrupted or timed out. Still registered. Semaphore not acquired.
+ now = runtime_nanotime();
+ if(now >= deadline)
+ break;
+
+ // Deadline hasn't arrived. Keep sleeping.
+ ns = deadline - now;
+ }
+
+ // Deadline arrived. Still registered. Semaphore not acquired.
+ // Want to give up and return, but have to unregister first,
+ // so that any notewakeup racing with the return does not
+ // try to grant us the semaphore when we don't expect it.
+ for(;;) {
+ mp = runtime_atomicloadp(&n->waitm);
+ if(mp == m) {
+ // No wakeup yet; unregister if possible.
+ if(runtime_casp(&n->waitm, mp, nil))
+ return;
+ } else if(mp == (M*)LOCKED) {
+ // Wakeup happened so semaphore is available.
+ // Grab it to avoid getting out of sync.
+ if(runtime_semasleep(-1) < 0)
+ runtime_throw("runtime: unable to acquire - semaphore out of sync");
+ return;
+ } else {
+ runtime_throw("runtime: unexpected waitm - semaphore out of sync");
+ }
+ }
+}
diff --git a/libgo/runtime/malloc.goc b/libgo/runtime/malloc.goc
index 66f5bda66c0..73446bf8347 100644
--- a/libgo/runtime/malloc.goc
+++ b/libgo/runtime/malloc.goc
@@ -33,14 +33,25 @@ extern volatile int32 runtime_MemProfileRate
void*
runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
{
+ M *m;
+ G *g;
int32 sizeclass, rate;
MCache *c;
uintptr npages;
MSpan *s;
void *v;
- if(!__sync_bool_compare_and_swap(&m->mallocing, 0, 1))
+ m = runtime_m();
+ g = runtime_g();
+ if(g->status == Gsyscall)
+ dogc = 0;
+ if(runtime_gcwaiting && g != m->g0 && m->locks == 0 && g->status != Gsyscall) {
+ runtime_gosched();
+ m = runtime_m();
+ }
+ if(m->mallocing)
runtime_throw("malloc/free - deadlock");
+ m->mallocing = 1;
if(size == 0)
size = 1;
@@ -63,7 +74,7 @@ runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
npages = size >> PageShift;
if((size & PageMask) != 0)
npages++;
- s = runtime_MHeap_Alloc(&runtime_mheap, npages, 0, 1);
+ s = runtime_MHeap_Alloc(&runtime_mheap, npages, 0, !(flag & FlagNoGC));
if(s == nil)
runtime_throw("out of memory");
size = npages<<PageShift;
@@ -77,18 +88,7 @@ runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
if(!(flag & FlagNoGC))
runtime_markallocated(v, size, (flag&FlagNoPointers) != 0);
- __sync_bool_compare_and_swap(&m->mallocing, 1, 0);
-
- if(__sync_bool_compare_and_swap(&m->gcing, 1, 0)) {
- if(!(flag & FlagNoProfiling))
- __go_run_goroutine_gc(0);
- else {
- // We are being called from the profiler. Tell it
- // to invoke the garbage collector when it is
- // done. No need to use a sync function here.
- m->gcing_for_prof = 1;
- }
- }
+ m->mallocing = 0;
if(!(flag & FlagNoProfiling) && (rate = runtime_MemProfileRate) > 0) {
if(size >= (uint32) rate)
@@ -122,6 +122,7 @@ __go_alloc(uintptr size)
void
__go_free(void *v)
{
+ M *m;
int32 sizeclass;
MSpan *s;
MCache *c;
@@ -134,8 +135,10 @@ __go_free(void *v)
// If you change this also change mgc0.c:/^sweepspan,
// which has a copy of the guts of free.
- if(!__sync_bool_compare_and_swap(&m->mallocing, 0, 1))
+ m = runtime_m();
+ if(m->mallocing)
runtime_throw("malloc/free - deadlock");
+ m->mallocing = 1;
if(!runtime_mlookup(v, nil, nil, &s)) {
// runtime_printf("free %p: not an allocated block\n", v);
@@ -170,11 +173,7 @@ __go_free(void *v)
c->local_alloc -= size;
if(prof)
runtime_MProf_Free(v, size);
-
- __sync_bool_compare_and_swap(&m->mallocing, 1, 0);
-
- if(__sync_bool_compare_and_swap(&m->gcing, 1, 0))
- __go_run_goroutine_gc(1);
+ m->mallocing = 0;
}
int32
@@ -184,7 +183,7 @@ runtime_mlookup(void *v, byte **base, uintptr *size, MSpan **sp)
byte *p;
MSpan *s;
- m->mcache->local_nlookup++;
+ runtime_m()->mcache->local_nlookup++;
s = runtime_MHeap_LookupMaybe(&runtime_mheap, v);
if(sp)
*sp = s;
@@ -229,15 +228,8 @@ runtime_allocmcache(void)
int32 rate;
MCache *c;
- if(!__sync_bool_compare_and_swap(&m->mallocing, 0, 1))
- runtime_throw("allocmcache - deadlock");
-
runtime_lock(&runtime_mheap);
c = runtime_FixAlloc_Alloc(&runtime_mheap.cachealloc);
-
- // Clear the free list used by FixAlloc; assume the rest is zeroed.
- c->list[0].list = nil;
-
mstats.mcache_inuse = runtime_mheap.cachealloc.inuse;
mstats.mcache_sys = runtime_mheap.cachealloc.sys;
runtime_unlock(&runtime_mheap);
@@ -249,10 +241,6 @@ runtime_allocmcache(void)
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);
-
return c;
}
@@ -374,13 +362,7 @@ runtime_mallocinit(void)
// Initialize the rest of the allocator.
runtime_MHeap_Init(&runtime_mheap, runtime_SysAlloc);
- m->mcache = runtime_allocmcache();
-
- // Initialize malloc profiling.
- runtime_Mprof_Init();
-
- // Initialize finalizer.
- runtime_initfintab();
+ runtime_m()->mcache = runtime_allocmcache();
// See if it works.
runtime_free(runtime_malloc(1));
diff --git a/libgo/runtime/malloc.h b/libgo/runtime/malloc.h
index 1ccc2f0b260..da0c0f85766 100644
--- a/libgo/runtime/malloc.h
+++ b/libgo/runtime/malloc.h
@@ -405,7 +405,6 @@ enum
FlagNoGC = 1<<2, // must not free or scan for pointers
};
-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));
@@ -423,4 +422,4 @@ extern int32 runtime_malloc_profile;
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));
+void runtime_walkfintab(void (*fn)(void*), void (*scan)(byte *, int64));
diff --git a/libgo/runtime/mcentral.c b/libgo/runtime/mcentral.c
index b98a8d32204..00c6f23a33d 100644
--- a/libgo/runtime/mcentral.c
+++ b/libgo/runtime/mcentral.c
@@ -26,7 +26,6 @@ static void MCentral_Free(MCentral *c, void *v);
void
runtime_MCentral_Init(MCentral *c, int32 sizeclass)
{
- runtime_initlock(c);
c->sizeclass = sizeclass;
runtime_MSpanList_Init(&c->nonempty);
runtime_MSpanList_Init(&c->empty);
diff --git a/libgo/runtime/mfinal.c b/libgo/runtime/mfinal.c
index db9a4fdf5ed..a8900371679 100644
--- a/libgo/runtime/mfinal.c
+++ b/libgo/runtime/mfinal.c
@@ -41,15 +41,6 @@ static struct {
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, void (*fn)(void*), const struct __go_func_type *ft)
{
@@ -150,28 +141,24 @@ 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");
-
tab = TAB(p);
runtime_lock(tab);
if(f == nil) {
if(lookfintab(tab, p, true, nil))
runtime_setblockspecial(p, false);
- ret = true;
- goto unlock;
+ runtime_unlock(tab);
+ return true;
}
if(lookfintab(tab, p, false, nil)) {
- ret = false;
- goto unlock;
+ runtime_unlock(tab);
+ return false;
}
if(tab->nkey >= tab->max/2+tab->max/4) {
@@ -182,18 +169,8 @@ runtime_addfinalizer(void *p, void (*f)(void*), const struct __go_func_type *ft)
addfintab(tab, p, f, ft);
runtime_setblockspecial(p, true);
- ret = true;
-
- unlock:
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;
+ return true;
}
// get finalizer; if del, delete finalizer.
@@ -205,19 +182,10 @@ runtime_getfinalizer(void *p, bool del, void (**fn)(void*), const struct __go_fu
bool res;
Fin f;
- if(!__sync_bool_compare_and_swap(&m->holds_finlock, 0, 1))
- runtime_throw("finalizer deadlock");
-
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);
- }
-
if(res==false)
return false;
*fn = f.fn;
@@ -232,9 +200,6 @@ runtime_walkfintab(void (*fn)(void*), void (*scan)(byte *, int64))
void **ekey;
int32 i;
- if(!__sync_bool_compare_and_swap(&m->holds_finlock, 0, 1))
- runtime_throw("finalizer deadlock");
-
for(i=0; i<TABSZ; i++) {
runtime_lock(&fintab[i]);
key = fintab[i].fkey;
@@ -246,9 +211,4 @@ runtime_walkfintab(void (*fn)(void*), void (*scan)(byte *, int64))
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)) {
- runtime_throw("walkfintab not called from gc");
- }
}
diff --git a/libgo/runtime/mgc0.c b/libgo/runtime/mgc0.c
index 6d402e55dd6..0f1cb49e40f 100644
--- a/libgo/runtime/mgc0.c
+++ b/libgo/runtime/mgc0.c
@@ -8,6 +8,16 @@
#include "arch.h"
#include "malloc.h"
+#ifdef USING_SPLIT_STACK
+
+extern void * __splitstack_find (void *, void *, size_t *, void **, void **,
+ void **);
+
+extern void * __splitstack_find_context (void *context[10], size_t *, void **,
+ void **, void **);
+
+#endif
+
enum {
Debug = 0,
PtrSize = sizeof(void*),
@@ -85,9 +95,8 @@ struct FinBlock
Finalizer fin[1];
};
-static bool finstarted;
-static pthread_mutex_t finqlock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t finqcond = PTHREAD_COND_INITIALIZER;
+
+static G *fing;
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
@@ -590,6 +599,79 @@ handoff(Workbuf *b)
return b1;
}
+// Scanstack calls scanblock on each of gp's stack segments.
+static void
+scanstack(void (*scanblock)(byte*, int64), G *gp)
+{
+#ifdef USING_SPLIT_STACK
+ M *mp;
+ void* sp;
+ size_t spsize;
+ void* next_segment;
+ void* next_sp;
+ void* initial_sp;
+
+ if(gp == runtime_g()) {
+ // Scanning our own stack.
+ sp = __splitstack_find(nil, nil, &spsize, &next_segment,
+ &next_sp, &initial_sp);
+ } else if((mp = gp->m) != nil && mp->helpgc) {
+ // gchelper's stack is in active use and has no interesting pointers.
+ return;
+ } else {
+ // Scanning another goroutine's stack.
+ // The goroutine is usually asleep (the world is stopped).
+
+ // The exception is that if the goroutine is about to enter or might
+ // have just exited a system call, it may be executing code such
+ // as schedlock and may have needed to start a new stack segment.
+ // Use the stack segment and stack pointer at the time of
+ // the system call instead, since that won't change underfoot.
+ if(gp->gcstack != nil) {
+ sp = gp->gcstack;
+ spsize = gp->gcstack_size;
+ next_segment = gp->gcnext_segment;
+ next_sp = gp->gcnext_sp;
+ initial_sp = gp->gcinitial_sp;
+ } else {
+ sp = __splitstack_find_context(&gp->stack_context[0],
+ &spsize, &next_segment,
+ &next_sp, &initial_sp);
+ }
+ }
+ if(sp != nil) {
+ scanblock(sp, spsize);
+ while((sp = __splitstack_find(next_segment, next_sp,
+ &spsize, &next_segment,
+ &next_sp, &initial_sp)) != nil)
+ scanblock(sp, spsize);
+ }
+#else
+ M *mp;
+ byte* bottom;
+ byte* top;
+
+ if(gp == runtime_g()) {
+ // Scanning our own stack.
+ bottom = (byte*)&gp;
+ } else if((mp = gp->m) != nil && mp->helpgc) {
+ // gchelper's stack is in active use and has no interesting pointers.
+ return;
+ } else {
+ // Scanning another goroutine's stack.
+ // The goroutine is usually asleep (the world is stopped).
+ bottom = (byte*)gp->gcnext_sp;
+ if(bottom == nil)
+ return;
+ }
+ top = (byte*)gp->gcinitial_sp + gp->gcstack_size;
+ if(top > bottom)
+ scanblock(bottom, top - bottom);
+ else
+ scanblock(top, bottom - top);
+#endif
+}
+
// Markfin calls scanblock on the blocks that have finalizers:
// the things pointed at cannot be freed until the finalizers have run.
static void
@@ -639,8 +721,10 @@ static void
mark(void (*scan)(byte*, int64))
{
struct root_list *pl;
+ G *gp;
FinBlock *fb;
+ // mark data+bss.
for(pl = roots; pl != nil; pl = pl->next) {
struct root* pr = &pl->roots[0];
while(1) {
@@ -654,11 +738,30 @@ mark(void (*scan)(byte*, int64))
scan((byte*)&runtime_m0, sizeof runtime_m0);
scan((byte*)&runtime_g0, sizeof runtime_g0);
- scan((byte*)&finq, sizeof finq);
+ scan((byte*)&runtime_allg, sizeof runtime_allg);
+ scan((byte*)&runtime_allm, sizeof runtime_allm);
runtime_MProf_Mark(scan);
// mark stacks
- __go_scanstacks(scan);
+ for(gp=runtime_allg; gp!=nil; gp=gp->alllink) {
+ switch(gp->status){
+ default:
+ runtime_printf("unexpected G.status %d\n", gp->status);
+ runtime_throw("mark - bad status");
+ case Gdead:
+ break;
+ case Grunning:
+ if(gp != runtime_g())
+ runtime_throw("mark - world not stopped");
+ scanstack(scan, gp);
+ break;
+ case Grunnable:
+ case Gsyscall:
+ case Gwaiting:
+ scanstack(scan, gp);
+ break;
+ }
+ }
// mark things pointed at by objects with finalizers
if(scan == debug_scanblock)
@@ -714,6 +817,7 @@ handlespecial(byte *p, uintptr size)
static void
sweep(void)
{
+ M *m;
MSpan *s;
int32 cl, n, npages;
uintptr size;
@@ -721,6 +825,7 @@ sweep(void)
MCache *c;
byte *arena_start;
+ m = runtime_m();
arena_start = runtime_mheap.arena_start;
for(;;) {
@@ -799,8 +904,6 @@ sweep(void)
}
}
-static pthread_mutex_t gcsema = PTHREAD_MUTEX_INITIALIZER;
-
void
runtime_gchelper(void)
{
@@ -818,6 +921,11 @@ runtime_gchelper(void)
runtime_notewakeup(&work.alldone);
}
+// Semaphore, not Lock, so that the goroutine
+// reschedules when there is contention rather
+// than spinning.
+static uint32 gcsema = 1;
+
// Initialized from $GOGC. GOGC=off means no gc.
//
// Next gc is after we've allocated an extra amount of
@@ -829,12 +937,49 @@ runtime_gchelper(void)
// extra memory used).
static int32 gcpercent = -2;
+static void
+stealcache(void)
+{
+ M *m;
+
+ for(m=runtime_allm; m; m=m->alllink)
+ runtime_MCache_ReleaseAll(m->mcache);
+}
+
+static void
+cachestats(void)
+{
+ M *m;
+ MCache *c;
+ uint32 i;
+ uint64 stacks_inuse;
+ uint64 stacks_sys;
+
+ stacks_inuse = 0;
+ stacks_sys = 0;
+ for(m=runtime_allm; m; m=m->alllink) {
+ runtime_purgecachedstats(m);
+ // stacks_inuse += m->stackalloc->inuse;
+ // stacks_sys += m->stackalloc->sys;
+ c = m->mcache;
+ for(i=0; i<nelem(c->local_by_size); i++) {
+ mstats.by_size[i].nmalloc += c->local_by_size[i].nmalloc;
+ c->local_by_size[i].nmalloc = 0;
+ mstats.by_size[i].nfree += c->local_by_size[i].nfree;
+ c->local_by_size[i].nfree = 0;
+ }
+ }
+ mstats.stacks_inuse = stacks_inuse;
+ mstats.stacks_sys = stacks_sys;
+}
+
void
-runtime_gc(int32 force __attribute__ ((unused)))
+runtime_gc(int32 force)
{
+ M *m;
int64 t0, t1, t2, t3;
uint64 heap0, heap1, obj0, obj1;
- char *p;
+ const byte *p;
bool extra;
// The gc is turned off (via enablegc) until
@@ -845,14 +990,15 @@ runtime_gc(int32 force __attribute__ ((unused)))
// problems, don't bother trying to run gc
// while holding a lock. The next mallocgc
// without a lock will do the gc instead.
- if(!mstats.enablegc || m->locks > 0 /* || runtime_panicking */)
+ m = runtime_m();
+ if(!mstats.enablegc || m->locks > 0 || runtime_panicking)
return;
if(gcpercent == -2) { // first time through
p = runtime_getenv("GOGC");
if(p == nil || p[0] == '\0')
gcpercent = 100;
- else if(runtime_strcmp(p, "off") == 0)
+ else if(runtime_strcmp((const char*)p, "off") == 0)
gcpercent = -1;
else
gcpercent = runtime_atoi(p);
@@ -860,21 +1006,13 @@ runtime_gc(int32 force __attribute__ ((unused)))
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;
- pthread_mutex_lock(&finqlock);
- pthread_mutex_lock(&gcsema);
+ runtime_semacquire(&gcsema);
if(!force && mstats.heap_alloc < mstats.next_gc) {
- pthread_mutex_unlock(&gcsema);
- pthread_mutex_unlock(&finqlock);
+ runtime_semrelease(&gcsema);
return;
}
@@ -887,7 +1025,7 @@ runtime_gc(int32 force __attribute__ ((unused)))
m->gcing = 1;
runtime_stoptheworld();
- __go_cachestats();
+ cachestats();
heap0 = mstats.heap_alloc;
obj0 = mstats.nmalloc - mstats.nfree;
@@ -896,12 +1034,10 @@ runtime_gc(int32 force __attribute__ ((unused)))
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;
@@ -918,14 +1054,25 @@ runtime_gc(int32 force __attribute__ ((unused)))
runtime_notesleep(&work.alldone);
t2 = runtime_nanotime();
- __go_stealcache();
- __go_cachestats();
+ stealcache();
+ cachestats();
mstats.next_gc = mstats.heap_alloc+mstats.heap_alloc*gcpercent/100;
m->gcing = 0;
m->locks++; // disable gc during the mallocs in newproc
+ if(finq != nil) {
+ // kick off or wake up goroutine to run queued finalizers
+ if(fing == nil)
+ fing = __go_go(runfinq, nil);
+ else if(fingwait) {
+ fingwait = 0;
+ runtime_ready(fing);
+ }
+ }
+ m->locks--;
+ cachestats();
heap1 = mstats.heap_alloc;
obj1 = mstats.nmalloc - mstats.nfree;
@@ -944,7 +1091,7 @@ runtime_gc(int32 force __attribute__ ((unused)))
(unsigned long long)nlookup, (unsigned long long)nsizelookup, (unsigned long long)naddrlookup, (unsigned long long) nhandoff);
}
- pthread_mutex_unlock(&gcsema);
+ runtime_semrelease(&gcsema);
// If we could have used another helper proc, start one now,
// in the hope that it will be available next time.
@@ -955,20 +1102,9 @@ runtime_gc(int32 force __attribute__ ((unused)))
// the maximum number of procs.
runtime_starttheworld(extra);
- // finqlock is still held.
- if(finq != nil) {
- // kick off or wake up goroutine to run queued finalizers
- if(!finstarted) {
- __go_go(runfinq, nil);
- finstarted = 1;
- }
- else if(fingwait) {
- fingwait = 0;
- pthread_cond_signal(&finqcond);
- }
- }
- m->locks--;
- pthread_mutex_unlock(&finqlock);
+ // give the queued finalizers, if any, a chance to run
+ if(finq != nil)
+ runtime_gosched();
if(gctrace > 1 && !force)
runtime_gc(1);
@@ -980,39 +1116,47 @@ void runtime_UpdateMemStats(void)
void
runtime_UpdateMemStats(void)
{
+ M *m;
+
// Have to acquire gcsema to stop the world,
// because stoptheworld can only be used by
// one goroutine at a time, and there might be
// a pending garbage collection already calling it.
- pthread_mutex_lock(&gcsema);
+ runtime_semacquire(&gcsema);
+ m = runtime_m();
m->gcing = 1;
runtime_stoptheworld();
- __go_cachestats();
+ cachestats();
m->gcing = 0;
- pthread_mutex_unlock(&gcsema);
+ runtime_semrelease(&gcsema);
runtime_starttheworld(false);
}
static void
-runfinq(void* dummy)
+runfinq(void* dummy __attribute__ ((unused)))
{
+ G* gp;
Finalizer *f;
FinBlock *fb, *next;
uint32 i;
- USED(dummy);
-
+ gp = runtime_g();
for(;;) {
- pthread_mutex_lock(&finqlock);
+ // There's no need for a lock in this section
+ // because it only conflicts with the garbage
+ // collector, and the garbage collector only
+ // runs when everyone else is stopped, and
+ // runfinq only stops at the gosched() or
+ // during the calls in the for loop.
fb = finq;
finq = nil;
if(fb == nil) {
fingwait = 1;
- pthread_cond_wait(&finqcond, &finqlock);
- pthread_mutex_unlock(&finqlock);
+ gp->status = Gwaiting;
+ gp->waitreason = "finalizer wait";
+ runtime_gosched();
continue;
}
- pthread_mutex_unlock(&finqlock);
for(; fb; fb=next) {
next = fb->next;
for(i=0; i<(uint32)fb->cnt; i++) {
@@ -1033,8 +1177,6 @@ runfinq(void* dummy)
}
}
-#define runtime_singleproc 0
-
// mark the block at v of size n as allocated.
// If noptr is true, mark it as having no pointers.
void
@@ -1237,9 +1379,3 @@ runtime_MHeap_MapBits(MHeap *h)
runtime_SysMap(h->arena_start - n, n - h->bitmap_mapped);
h->bitmap_mapped = n;
}
-
-void
-__go_enable_gc()
-{
- mstats.enablegc = 1;
-}
diff --git a/libgo/runtime/mheap.c b/libgo/runtime/mheap.c
index a49b405a3e2..5a5a1e71a12 100644
--- a/libgo/runtime/mheap.c
+++ b/libgo/runtime/mheap.c
@@ -40,7 +40,6 @@ runtime_MHeap_Init(MHeap *h, void *(*alloc)(uintptr))
{
uint32 i;
- runtime_initlock(h);
runtime_FixAlloc_Init(&h->spanalloc, sizeof(MSpan), alloc, RecordSpan, h);
runtime_FixAlloc_Init(&h->cachealloc, sizeof(MCache), alloc, nil, nil);
// h->mapcache needs no init
@@ -59,7 +58,7 @@ runtime_MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, int32 acct)
MSpan *s;
runtime_lock(h);
- runtime_purgecachedstats(m);
+ runtime_purgecachedstats(runtime_m());
s = MHeap_AllocLocked(h, npage, sizeclass);
if(s != nil) {
mstats.heap_inuse += npage<<PageShift;
@@ -258,7 +257,7 @@ void
runtime_MHeap_Free(MHeap *h, MSpan *s, int32 acct)
{
runtime_lock(h);
- runtime_purgecachedstats(m);
+ runtime_purgecachedstats(runtime_m());
mstats.heap_inuse -= s->npages<<PageShift;
if(acct) {
mstats.heap_alloc -= s->npages<<PageShift;
diff --git a/libgo/runtime/mprof.goc b/libgo/runtime/mprof.goc
index 23c4f906f80..f44f45083f7 100644
--- a/libgo/runtime/mprof.goc
+++ b/libgo/runtime/mprof.goc
@@ -186,22 +186,20 @@ found:
return nil;
}
-void
-runtime_Mprof_Init()
-{
- runtime_initlock(&proflock);
-}
-
// Called by malloc to record a profiled block.
void
runtime_MProf_Malloc(void *p, uintptr size)
{
+ M *m;
int32 nstk;
uintptr stk[32];
Bucket *b;
- if(!__sync_bool_compare_and_swap(&m->nomemprof, 0, 1))
+ m = runtime_m();
+ if(m->nomemprof > 0)
return;
+
+ m->nomemprof++;
#if 0
nstk = runtime_callers(1, stk, 32);
#else
@@ -213,21 +211,22 @@ runtime_MProf_Malloc(void *p, uintptr size)
b->alloc_bytes += size;
setaddrbucket((uintptr)p, b);
runtime_unlock(&proflock);
- __sync_bool_compare_and_swap(&m->nomemprof, 1, 0);
-
- if(__sync_bool_compare_and_swap(&m->gcing_for_prof, 1, 0))
- __go_run_goroutine_gc(100);
+ m = runtime_m();
+ m->nomemprof--;
}
// Called when freeing a profiled block.
void
runtime_MProf_Free(void *p, uintptr size)
{
+ M *m;
Bucket *b;
- if(!__sync_bool_compare_and_swap(&m->nomemprof, 0, 1))
+ m = runtime_m();
+ if(m->nomemprof > 0)
return;
+ m->nomemprof++;
runtime_lock(&proflock);
b = getaddrbucket((uintptr)p);
if(b != nil) {
@@ -235,10 +234,8 @@ runtime_MProf_Free(void *p, uintptr size)
b->free_bytes += size;
}
runtime_unlock(&proflock);
- __sync_bool_compare_and_swap(&m->nomemprof, 1, 0);
-
- if(__sync_bool_compare_and_swap(&m->gcing_for_prof, 1, 0))
- __go_run_goroutine_gc(101);
+ m = runtime_m();
+ m->nomemprof--;
}
@@ -273,8 +270,6 @@ func MemProfile(p Slice, include_inuse_zero bool) (n int32, ok bool) {
Bucket *b;
Record *r;
- __sync_bool_compare_and_swap(&m->nomemprof, 0, 1);
-
runtime_lock(&proflock);
n = 0;
for(b=buckets; b; b=b->allnext)
@@ -289,11 +284,6 @@ func MemProfile(p Slice, include_inuse_zero bool) (n int32, ok bool) {
record(r++, b);
}
runtime_unlock(&proflock);
-
- __sync_bool_compare_and_swap(&m->nomemprof, 1, 0);
-
- if(__sync_bool_compare_and_swap(&m->gcing_for_prof, 1, 0))
- __go_run_goroutine_gc(102);
}
void
diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c
index e9b7c9083ca..b243de2424e 100644
--- a/libgo/runtime/proc.c
+++ b/libgo/runtime/proc.c
@@ -2,21 +2,1323 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include <limits.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include "config.h"
#include "runtime.h"
#include "arch.h"
-#include "malloc.h" /* so that acid generated from proc.c includes malloc data structures */
+#include "defs.h"
+#include "malloc.h"
+#include "go-defer.h"
+
+#ifdef USING_SPLIT_STACK
+
+/* FIXME: These are not declared anywhere. */
+
+extern void __splitstack_getcontext(void *context[10]);
+
+extern void __splitstack_setcontext(void *context[10]);
+
+extern void *__splitstack_makecontext(size_t, void *context[10], size_t *);
+
+extern void * __splitstack_resetcontext(void *context[10], size_t *);
+
+extern void *__splitstack_find(void *, void *, size_t *, void **, void **,
+ void **);
+
+#endif
+
+#if defined(USING_SPLIT_STACK) && defined(LINKER_SUPPORTS_SPLIT_STACK)
+# ifdef PTHREAD_STACK_MIN
+# define StackMin PTHREAD_STACK_MIN
+# else
+# define StackMin 8192
+# endif
+#else
+# define StackMin 2 * 1024 * 1024
+#endif
+
+static void schedule(G*);
+static M *startm(void);
typedef struct Sched Sched;
-G runtime_g0;
M runtime_m0;
+G runtime_g0; // idle goroutine for m0
#ifdef __rtems__
#define __thread
#endif
-__thread G *g;
-__thread M *m;
+static __thread G *g;
+static __thread M *m;
+
+// We can not always refer to the TLS variables directly. The
+// compiler will call tls_get_addr to get the address of the variable,
+// and it may hold it in a register across a call to schedule. When
+// we get back from the call we may be running in a different thread,
+// in which case the register now points to the TLS variable for a
+// different thread. We use non-inlinable functions to avoid this
+// when necessary.
+
+G* runtime_g(void) __attribute__ ((noinline, no_split_stack));
+
+G*
+runtime_g(void)
+{
+ return g;
+}
+
+M* runtime_m(void) __attribute__ ((noinline, no_split_stack));
+
+M*
+runtime_m(void)
+{
+ return m;
+}
+
+int32 runtime_gcwaiting;
+
+// Go scheduler
+//
+// The go scheduler's job is to match ready-to-run goroutines (`g's)
+// with waiting-for-work schedulers (`m's). If there are ready g's
+// and no waiting m's, ready() will start a new m running in a new
+// OS thread, so that all ready g's can run simultaneously, up to a limit.
+// For now, m's never go away.
+//
+// By default, Go keeps only one kernel thread (m) running user code
+// at a single time; other threads may be blocked in the operating system.
+// Setting the environment variable $GOMAXPROCS or calling
+// runtime.GOMAXPROCS() will change the number of user threads
+// allowed to execute simultaneously. $GOMAXPROCS is thus an
+// approximation of the maximum number of cores to use.
+//
+// Even a program that can run without deadlock in a single process
+// might use more m's if given the chance. For example, the prime
+// sieve will use as many m's as there are primes (up to runtime_sched.mmax),
+// allowing different stages of the pipeline to execute in parallel.
+// We could revisit this choice, only kicking off new m's for blocking
+// system calls, but that would limit the amount of parallel computation
+// that go would try to do.
+//
+// In general, one could imagine all sorts of refinements to the
+// scheduler, but the goal now is just to get something working on
+// Linux and OS X.
+
+struct Sched {
+ Lock;
+
+ G *gfree; // available g's (status == Gdead)
+ int32 goidgen;
+
+ G *ghead; // g's waiting to run
+ G *gtail;
+ int32 gwait; // number of g's waiting to run
+ int32 gcount; // number of g's that are alive
+ int32 grunning; // number of g's running on cpu or in syscall
+
+ M *mhead; // m's waiting for work
+ int32 mwait; // number of m's waiting for work
+ int32 mcount; // number of m's that have been created
+
+ volatile uint32 atomic; // atomic scheduling word (see below)
+
+ int32 profilehz; // cpu profiling rate
+
+ Note stopped; // one g can set waitstop and wait here for m's to stop
+};
+
+// The atomic word in sched is an atomic uint32 that
+// holds these fields.
+//
+// [15 bits] mcpu number of m's executing on cpu
+// [15 bits] mcpumax max number of m's allowed on cpu
+// [1 bit] waitstop some g is waiting on stopped
+// [1 bit] gwaiting gwait != 0
+//
+// These fields are the information needed by entersyscall
+// and exitsyscall to decide whether to coordinate with the
+// scheduler. Packing them into a single machine word lets
+// them use a fast path with a single atomic read/write and
+// no lock/unlock. This greatly reduces contention in
+// syscall- or cgo-heavy multithreaded programs.
+//
+// Except for entersyscall and exitsyscall, the manipulations
+// to these fields only happen while holding the schedlock,
+// so the routines holding schedlock only need to worry about
+// what entersyscall and exitsyscall do, not the other routines
+// (which also use the schedlock).
+//
+// In particular, entersyscall and exitsyscall only read mcpumax,
+// waitstop, and gwaiting. They never write them. Thus, writes to those
+// fields can be done (holding schedlock) without fear of write conflicts.
+// There may still be logic conflicts: for example, the set of waitstop must
+// be conditioned on mcpu >= mcpumax or else the wait may be a
+// spurious sleep. The Promela model in proc.p verifies these accesses.
+enum {
+ mcpuWidth = 15,
+ mcpuMask = (1<<mcpuWidth) - 1,
+ mcpuShift = 0,
+ mcpumaxShift = mcpuShift + mcpuWidth,
+ waitstopShift = mcpumaxShift + mcpuWidth,
+ gwaitingShift = waitstopShift+1,
+
+ // The max value of GOMAXPROCS is constrained
+ // by the max value we can store in the bit fields
+ // of the atomic word. Reserve a few high values
+ // so that we can detect accidental decrement
+ // beyond zero.
+ maxgomaxprocs = mcpuMask - 10,
+};
+
+#define atomic_mcpu(v) (((v)>>mcpuShift)&mcpuMask)
+#define atomic_mcpumax(v) (((v)>>mcpumaxShift)&mcpuMask)
+#define atomic_waitstop(v) (((v)>>waitstopShift)&1)
+#define atomic_gwaiting(v) (((v)>>gwaitingShift)&1)
+
+Sched runtime_sched;
+int32 runtime_gomaxprocs;
+bool runtime_singleproc;
+
+static bool canaddmcpu(void);
+
+// An m that is waiting for notewakeup(&m->havenextg). This may
+// only be accessed while the scheduler lock is held. This is used to
+// minimize the number of times we call notewakeup while the scheduler
+// lock is held, since the m will normally move quickly to lock the
+// scheduler itself, producing lock contention.
+static M* mwakeup;
+
+// Scheduling helpers. Sched must be locked.
+static void gput(G*); // put/get on ghead/gtail
+static G* gget(void);
+static void mput(M*); // put/get on mhead
+static M* mget(G*);
+static void gfput(G*); // put/get on gfree
+static G* gfget(void);
+static void matchmg(void); // match m's to g's
+static void readylocked(G*); // ready, but sched is locked
+static void mnextg(M*, G*);
+static void mcommoninit(M*);
+
+void
+setmcpumax(uint32 n)
+{
+ uint32 v, w;
+
+ for(;;) {
+ v = runtime_sched.atomic;
+ w = v;
+ w &= ~(mcpuMask<<mcpumaxShift);
+ w |= n<<mcpumaxShift;
+ if(runtime_cas(&runtime_sched.atomic, v, w))
+ break;
+ }
+}
+
+// First function run by a new goroutine. This replaces gogocall.
+static void
+kickoff(void)
+{
+ void (*fn)(void*);
+
+ fn = (void (*)(void*))(g->entry);
+ fn(g->param);
+ runtime_goexit();
+}
+
+// Switch context to a different goroutine. This is like longjmp.
+static void runtime_gogo(G*) __attribute__ ((noinline));
+static void
+runtime_gogo(G* newg)
+{
+#ifdef USING_SPLIT_STACK
+ __splitstack_setcontext(&newg->stack_context[0]);
+#endif
+ g = newg;
+ newg->fromgogo = true;
+ setcontext(&newg->context);
+}
+
+// Save context and call fn passing g as a parameter. This is like
+// setjmp. Because getcontext always returns 0, unlike setjmp, we use
+// g->fromgogo as a code. It will be true if we got here via
+// setcontext. g == nil the first time this is called in a new m.
+static void runtime_mcall(void (*)(G*)) __attribute__ ((noinline));
+static void
+runtime_mcall(void (*pfn)(G*))
+{
+#ifndef USING_SPLIT_STACK
+ int i;
+#endif
+
+ // Ensure that all registers are on the stack for the garbage
+ // collector.
+ __builtin_unwind_init();
+
+ if(g == m->g0)
+ runtime_throw("runtime: mcall called on m->g0 stack");
+
+ if(g != nil) {
+
+#ifdef USING_SPLIT_STACK
+ __splitstack_getcontext(&g->stack_context[0]);
+#else
+ g->gcnext_sp = &i;
+#endif
+ g->fromgogo = false;
+ getcontext(&g->context);
+ }
+ if (g == nil || !g->fromgogo) {
+#ifdef USING_SPLIT_STACK
+ __splitstack_setcontext(&m->g0->stack_context[0]);
+#endif
+ m->g0->entry = (byte*)pfn;
+ m->g0->param = g;
+ g = m->g0;
+ setcontext(&m->g0->context);
+ runtime_throw("runtime: mcall function returned");
+ }
+}
+
+// The bootstrap sequence is:
+//
+// call osinit
+// call schedinit
+// make & queue new G
+// call runtime_mstart
+//
+// The new G does:
+//
+// call main_init_function
+// call initdone
+// call main_main
+void
+runtime_schedinit(void)
+{
+ int32 n;
+ const byte *p;
+
+ m = &runtime_m0;
+ g = &runtime_g0;
+ m->g0 = g;
+ m->curg = g;
+ g->m = m;
+
+ m->nomemprof++;
+ runtime_mallocinit();
+ mcommoninit(m);
+
+ runtime_goargs();
+ runtime_goenvs();
+
+ // For debugging:
+ // Allocate internal symbol table representation now,
+ // so that we don't need to call malloc when we crash.
+ // runtime_findfunc(0);
+
+ runtime_gomaxprocs = 1;
+ p = runtime_getenv("GOMAXPROCS");
+ if(p != nil && (n = runtime_atoi(p)) != 0) {
+ if(n > maxgomaxprocs)
+ n = maxgomaxprocs;
+ runtime_gomaxprocs = n;
+ }
+ setmcpumax(runtime_gomaxprocs);
+ runtime_singleproc = runtime_gomaxprocs == 1;
+
+ canaddmcpu(); // mcpu++ to account for bootstrap m
+ m->helpgc = 1; // flag to tell schedule() to mcpu--
+ runtime_sched.grunning++;
+
+ // Can not enable GC until all roots are registered.
+ // mstats.enablegc = 1;
+ m->nomemprof--;
+}
+
+// Lock the scheduler.
+static void
+schedlock(void)
+{
+ runtime_lock(&runtime_sched);
+}
+
+// Unlock the scheduler.
+static void
+schedunlock(void)
+{
+ M *m;
+
+ m = mwakeup;
+ mwakeup = nil;
+ runtime_unlock(&runtime_sched);
+ if(m != nil)
+ runtime_notewakeup(&m->havenextg);
+}
+
+void
+runtime_goexit(void)
+{
+ g->status = Gmoribund;
+ runtime_gosched();
+}
+
+void
+runtime_goroutineheader(G *g)
+{
+ const char *status;
+
+ switch(g->status) {
+ case Gidle:
+ status = "idle";
+ break;
+ case Grunnable:
+ status = "runnable";
+ break;
+ case Grunning:
+ status = "running";
+ break;
+ case Gsyscall:
+ status = "syscall";
+ break;
+ case Gwaiting:
+ if(g->waitreason)
+ status = g->waitreason;
+ else
+ status = "waiting";
+ break;
+ case Gmoribund:
+ status = "moribund";
+ break;
+ default:
+ status = "???";
+ break;
+ }
+ runtime_printf("goroutine %d [%s]:\n", g->goid, status);
+}
+
+void
+runtime_tracebackothers(G *me)
+{
+ G *g;
+
+ for(g = runtime_allg; g != nil; g = g->alllink) {
+ if(g == me || g->status == Gdead)
+ continue;
+ runtime_printf("\n");
+ runtime_goroutineheader(g);
+ // runtime_traceback(g->sched.pc, g->sched.sp, 0, g);
+ }
+}
+
+// Mark this g as m's idle goroutine.
+// This functionality might be used in environments where programs
+// are limited to a single thread, to simulate a select-driven
+// network server. It is not exposed via the standard runtime API.
+void
+runtime_idlegoroutine(void)
+{
+ if(g->idlem != nil)
+ runtime_throw("g is already an idle goroutine");
+ g->idlem = m;
+}
+
+static void
+mcommoninit(M *m)
+{
+ // Add to runtime_allm so garbage collector doesn't free m
+ // when it is just in a register or thread-local storage.
+ m->alllink = runtime_allm;
+ // runtime_Cgocalls() iterates over allm w/o schedlock,
+ // so we need to publish it safely.
+ runtime_atomicstorep((void**)&runtime_allm, m);
+
+ m->id = runtime_sched.mcount++;
+ m->fastrand = 0x49f6428aUL + m->id;
+
+ if(m->mcache == nil)
+ m->mcache = runtime_allocmcache();
+}
+
+// Try to increment mcpu. Report whether succeeded.
+static bool
+canaddmcpu(void)
+{
+ uint32 v;
+
+ for(;;) {
+ v = runtime_sched.atomic;
+ if(atomic_mcpu(v) >= atomic_mcpumax(v))
+ return 0;
+ if(runtime_cas(&runtime_sched.atomic, v, v+(1<<mcpuShift)))
+ return 1;
+ }
+}
+
+// Put on `g' queue. Sched must be locked.
+static void
+gput(G *g)
+{
+ M *m;
+
+ // If g is wired, hand it off directly.
+ if((m = g->lockedm) != nil && canaddmcpu()) {
+ mnextg(m, g);
+ return;
+ }
+
+ // If g is the idle goroutine for an m, hand it off.
+ if(g->idlem != nil) {
+ if(g->idlem->idleg != nil) {
+ runtime_printf("m%d idle out of sync: g%d g%d\n",
+ g->idlem->id,
+ g->idlem->idleg->goid, g->goid);
+ runtime_throw("runtime: double idle");
+ }
+ g->idlem->idleg = g;
+ return;
+ }
+
+ g->schedlink = nil;
+ if(runtime_sched.ghead == nil)
+ runtime_sched.ghead = g;
+ else
+ runtime_sched.gtail->schedlink = g;
+ runtime_sched.gtail = g;
+
+ // increment gwait.
+ // if it transitions to nonzero, set atomic gwaiting bit.
+ if(runtime_sched.gwait++ == 0)
+ runtime_xadd(&runtime_sched.atomic, 1<<gwaitingShift);
+}
+
+// Report whether gget would return something.
+static bool
+haveg(void)
+{
+ return runtime_sched.ghead != nil || m->idleg != nil;
+}
+
+// Get from `g' queue. Sched must be locked.
+static G*
+gget(void)
+{
+ G *g;
+
+ g = runtime_sched.ghead;
+ if(g){
+ runtime_sched.ghead = g->schedlink;
+ if(runtime_sched.ghead == nil)
+ runtime_sched.gtail = nil;
+ // decrement gwait.
+ // if it transitions to zero, clear atomic gwaiting bit.
+ if(--runtime_sched.gwait == 0)
+ runtime_xadd(&runtime_sched.atomic, -1<<gwaitingShift);
+ } else if(m->idleg != nil) {
+ g = m->idleg;
+ m->idleg = nil;
+ }
+ return g;
+}
+
+// Put on `m' list. Sched must be locked.
+static void
+mput(M *m)
+{
+ m->schedlink = runtime_sched.mhead;
+ runtime_sched.mhead = m;
+ runtime_sched.mwait++;
+}
+
+// Get an `m' to run `g'. Sched must be locked.
+static M*
+mget(G *g)
+{
+ M *m;
+
+ // if g has its own m, use it.
+ if(g && (m = g->lockedm) != nil)
+ return m;
+
+ // otherwise use general m pool.
+ if((m = runtime_sched.mhead) != nil){
+ runtime_sched.mhead = m->schedlink;
+ runtime_sched.mwait--;
+ }
+ return m;
+}
+
+// Mark g ready to run.
+void
+runtime_ready(G *g)
+{
+ schedlock();
+ readylocked(g);
+ schedunlock();
+}
+
+// Mark g ready to run. Sched is already locked.
+// G might be running already and about to stop.
+// The sched lock protects g->status from changing underfoot.
+static void
+readylocked(G *g)
+{
+ if(g->m){
+ // Running on another machine.
+ // Ready it when it stops.
+ g->readyonstop = 1;
+ return;
+ }
+
+ // Mark runnable.
+ if(g->status == Grunnable || g->status == Grunning) {
+ runtime_printf("goroutine %d has status %d\n", g->goid, g->status);
+ runtime_throw("bad g->status in ready");
+ }
+ g->status = Grunnable;
+
+ gput(g);
+ matchmg();
+}
+
+// Same as readylocked but a different symbol so that
+// debuggers can set a breakpoint here and catch all
+// new goroutines.
+static void
+newprocreadylocked(G *g)
+{
+ readylocked(g);
+}
+
+// Pass g to m for running.
+// Caller has already incremented mcpu.
+static void
+mnextg(M *m, G *g)
+{
+ runtime_sched.grunning++;
+ m->nextg = g;
+ if(m->waitnextg) {
+ m->waitnextg = 0;
+ if(mwakeup != nil)
+ runtime_notewakeup(&mwakeup->havenextg);
+ mwakeup = m;
+ }
+}
+
+// Get the next goroutine that m should run.
+// Sched must be locked on entry, is unlocked on exit.
+// Makes sure that at most $GOMAXPROCS g's are
+// running on cpus (not in system calls) at any given time.
+static G*
+nextgandunlock(void)
+{
+ G *gp;
+ uint32 v;
+
+top:
+ if(atomic_mcpu(runtime_sched.atomic) >= maxgomaxprocs)
+ runtime_throw("negative mcpu");
+
+ // If there is a g waiting as m->nextg, the mcpu++
+ // happened before it was passed to mnextg.
+ if(m->nextg != nil) {
+ gp = m->nextg;
+ m->nextg = nil;
+ schedunlock();
+ return gp;
+ }
+
+ if(m->lockedg != nil) {
+ // We can only run one g, and it's not available.
+ // Make sure some other cpu is running to handle
+ // the ordinary run queue.
+ if(runtime_sched.gwait != 0) {
+ matchmg();
+ // m->lockedg might have been on the queue.
+ if(m->nextg != nil) {
+ gp = m->nextg;
+ m->nextg = nil;
+ schedunlock();
+ return gp;
+ }
+ }
+ } else {
+ // Look for work on global queue.
+ while(haveg() && canaddmcpu()) {
+ gp = gget();
+ if(gp == nil)
+ runtime_throw("gget inconsistency");
+
+ if(gp->lockedm) {
+ mnextg(gp->lockedm, gp);
+ continue;
+ }
+ runtime_sched.grunning++;
+ schedunlock();
+ return gp;
+ }
+
+ // The while loop ended either because the g queue is empty
+ // or because we have maxed out our m procs running go
+ // code (mcpu >= mcpumax). We need to check that
+ // concurrent actions by entersyscall/exitsyscall cannot
+ // invalidate the decision to end the loop.
+ //
+ // We hold the sched lock, so no one else is manipulating the
+ // g queue or changing mcpumax. Entersyscall can decrement
+ // mcpu, but if does so when there is something on the g queue,
+ // the gwait bit will be set, so entersyscall will take the slow path
+ // and use the sched lock. So it cannot invalidate our decision.
+ //
+ // Wait on global m queue.
+ mput(m);
+ }
+
+ v = runtime_atomicload(&runtime_sched.atomic);
+ if(runtime_sched.grunning == 0)
+ runtime_throw("all goroutines are asleep - deadlock!");
+ m->nextg = nil;
+ m->waitnextg = 1;
+ runtime_noteclear(&m->havenextg);
+
+ // Stoptheworld is waiting for all but its cpu to go to stop.
+ // Entersyscall might have decremented mcpu too, but if so
+ // it will see the waitstop and take the slow path.
+ // Exitsyscall never increments mcpu beyond mcpumax.
+ if(atomic_waitstop(v) && atomic_mcpu(v) <= atomic_mcpumax(v)) {
+ // set waitstop = 0 (known to be 1)
+ runtime_xadd(&runtime_sched.atomic, -1<<waitstopShift);
+ runtime_notewakeup(&runtime_sched.stopped);
+ }
+ schedunlock();
+
+ runtime_notesleep(&m->havenextg);
+ if(m->helpgc) {
+ runtime_gchelper();
+ m->helpgc = 0;
+ runtime_lock(&runtime_sched);
+ goto top;
+ }
+ if((gp = m->nextg) == nil)
+ runtime_throw("bad m->nextg in nextgoroutine");
+ m->nextg = nil;
+ return gp;
+}
+
+int32
+runtime_helpgc(bool *extra)
+{
+ M *mp;
+ int32 n, max;
+
+ // Figure out how many CPUs to use.
+ // Limited by gomaxprocs, number of actual CPUs, and MaxGcproc.
+ max = runtime_gomaxprocs;
+ if(max > runtime_ncpu)
+ max = runtime_ncpu > 0 ? runtime_ncpu : 1;
+ if(max > MaxGcproc)
+ max = MaxGcproc;
+
+ // We're going to use one CPU no matter what.
+ // Figure out the max number of additional CPUs.
+ max--;
+
+ runtime_lock(&runtime_sched);
+ n = 0;
+ while(n < max && (mp = mget(nil)) != nil) {
+ n++;
+ mp->helpgc = 1;
+ mp->waitnextg = 0;
+ runtime_notewakeup(&mp->havenextg);
+ }
+ runtime_unlock(&runtime_sched);
+ if(extra)
+ *extra = n != max;
+ return n;
+}
+
+void
+runtime_stoptheworld(void)
+{
+ uint32 v;
+
+ schedlock();
+ runtime_gcwaiting = 1;
+
+ setmcpumax(1);
+
+ // while mcpu > 1
+ for(;;) {
+ v = runtime_sched.atomic;
+ if(atomic_mcpu(v) <= 1)
+ break;
+
+ // It would be unsafe for multiple threads to be using
+ // the stopped note at once, but there is only
+ // ever one thread doing garbage collection.
+ runtime_noteclear(&runtime_sched.stopped);
+ if(atomic_waitstop(v))
+ runtime_throw("invalid waitstop");
+
+ // atomic { waitstop = 1 }, predicated on mcpu <= 1 check above
+ // still being true.
+ if(!runtime_cas(&runtime_sched.atomic, v, v+(1<<waitstopShift)))
+ continue;
+
+ schedunlock();
+ runtime_notesleep(&runtime_sched.stopped);
+ schedlock();
+ }
+ runtime_singleproc = runtime_gomaxprocs == 1;
+ schedunlock();
+}
+
+void
+runtime_starttheworld(bool extra)
+{
+ M *m;
+
+ schedlock();
+ runtime_gcwaiting = 0;
+ setmcpumax(runtime_gomaxprocs);
+ matchmg();
+ if(extra && canaddmcpu()) {
+ // Start a new m that will (we hope) be idle
+ // and so available to help when the next
+ // garbage collection happens.
+ // canaddmcpu above did mcpu++
+ // (necessary, because m will be doing various
+ // initialization work so is definitely running),
+ // but m is not running a specific goroutine,
+ // so set the helpgc flag as a signal to m's
+ // first schedule(nil) to mcpu-- and grunning--.
+ m = startm();
+ m->helpgc = 1;
+ runtime_sched.grunning++;
+ }
+ schedunlock();
+}
+
+// Called to start an M.
+void*
+runtime_mstart(void* mp)
+{
+ m = (M*)mp;
+ g = m->g0;
+
+ g->entry = nil;
+ g->param = nil;
+
+ // Record top of stack for use by mcall.
+ // Once we call schedule we're never coming back,
+ // so other calls can reuse this stack space.
+#ifdef USING_SPLIT_STACK
+ __splitstack_getcontext(&g->stack_context[0]);
+#else
+ g->gcinitial_sp = &mp;
+ g->gcstack_size = StackMin;
+ g->gcnext_sp = &mp;
+#endif
+ getcontext(&g->context);
+
+ if(g->entry != nil) {
+ // Got here from mcall.
+ void (*pfn)(G*) = (void (*)(G*))g->entry;
+ G* gp = (G*)g->param;
+ pfn(gp);
+ *(int*)0x21 = 0x21;
+ }
+ runtime_minit();
+ schedule(nil);
+ return nil;
+}
+
+typedef struct CgoThreadStart CgoThreadStart;
+struct CgoThreadStart
+{
+ M *m;
+ G *g;
+ void (*fn)(void);
+};
+
+// Kick off new m's as needed (up to mcpumax).
+// There are already `other' other cpus that will
+// start looking for goroutines shortly.
+// Sched is locked.
+static void
+matchmg(void)
+{
+ G *gp;
+ M *mp;
+
+ if(m->mallocing || m->gcing)
+ return;
+
+ while(haveg() && canaddmcpu()) {
+ gp = gget();
+ if(gp == nil)
+ runtime_throw("gget inconsistency");
+
+ // Find the m that will run gp.
+ if((mp = mget(gp)) == nil)
+ mp = startm();
+ mnextg(mp, gp);
+ }
+}
+
+static M*
+startm(void)
+{
+ M *m;
+ pthread_attr_t attr;
+ pthread_t tid;
+
+ m = runtime_malloc(sizeof(M));
+ mcommoninit(m);
+ m->g0 = runtime_malg(-1, nil, nil);
+
+ if(pthread_attr_init(&attr) != 0)
+ runtime_throw("pthread_attr_init");
+ if(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
+ runtime_throw("pthread_attr_setdetachstate");
+
+#ifndef PTHREAD_STACK_MIN
+#define PTHREAD_STACK_MIN 8192
+#endif
+ if(pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN) != 0)
+ runtime_throw("pthread_attr_setstacksize");
+
+ if(pthread_create(&tid, &attr, runtime_mstart, m) != 0)
+ runtime_throw("pthread_create");
+
+ return m;
+}
+
+// One round of scheduler: find a goroutine and run it.
+// The argument is the goroutine that was running before
+// schedule was called, or nil if this is the first call.
+// Never returns.
+static void
+schedule(G *gp)
+{
+ int32 hz;
+ uint32 v;
+
+ schedlock();
+ if(gp != nil) {
+ // Just finished running gp.
+ gp->m = nil;
+ runtime_sched.grunning--;
+
+ // atomic { mcpu-- }
+ v = runtime_xadd(&runtime_sched.atomic, -1<<mcpuShift);
+ if(atomic_mcpu(v) > maxgomaxprocs)
+ runtime_throw("negative mcpu in scheduler");
+
+ switch(gp->status){
+ case Grunnable:
+ case Gdead:
+ // Shouldn't have been running!
+ runtime_throw("bad gp->status in sched");
+ case Grunning:
+ gp->status = Grunnable;
+ gput(gp);
+ break;
+ case Gmoribund:
+ gp->status = Gdead;
+ if(gp->lockedm) {
+ gp->lockedm = nil;
+ m->lockedg = nil;
+ }
+ gp->idlem = nil;
+ gfput(gp);
+ if(--runtime_sched.gcount == 0)
+ runtime_exit(0);
+ break;
+ }
+ if(gp->readyonstop){
+ gp->readyonstop = 0;
+ readylocked(gp);
+ }
+ } else if(m->helpgc) {
+ // Bootstrap m or new m started by starttheworld.
+ // atomic { mcpu-- }
+ v = runtime_xadd(&runtime_sched.atomic, -1<<mcpuShift);
+ if(atomic_mcpu(v) > maxgomaxprocs)
+ runtime_throw("negative mcpu in scheduler");
+ // Compensate for increment in starttheworld().
+ runtime_sched.grunning--;
+ m->helpgc = 0;
+ } else if(m->nextg != nil) {
+ // New m started by matchmg.
+ } else {
+ runtime_throw("invalid m state in scheduler");
+ }
+
+ // Find (or wait for) g to run. Unlocks runtime_sched.
+ gp = nextgandunlock();
+ gp->readyonstop = 0;
+ gp->status = Grunning;
+ m->curg = gp;
+ gp->m = m;
+
+ // Check whether the profiler needs to be turned on or off.
+ hz = runtime_sched.profilehz;
+ if(m->profilehz != hz)
+ runtime_resetcpuprofiler(hz);
+
+ runtime_gogo(gp);
+}
+
+// Enter scheduler. If g->status is Grunning,
+// re-queues g and runs everyone else who is waiting
+// before running g again. If g->status is Gmoribund,
+// kills off g.
+void
+runtime_gosched(void)
+{
+ if(m->locks != 0)
+ runtime_throw("gosched holding locks");
+ if(g == m->g0)
+ runtime_throw("gosched of g0");
+ runtime_mcall(schedule);
+}
+
+// The goroutine g is about to enter a system call.
+// Record that it's not using the cpu anymore.
+// This is called only from the go syscall library and cgocall,
+// not from the low-level system calls used by the runtime.
+//
+// Entersyscall cannot split the stack: the runtime_gosave must
+// make g->sched refer to the caller's stack segment, because
+// entersyscall is going to return immediately after.
+// It's okay to call matchmg and notewakeup even after
+// decrementing mcpu, because we haven't released the
+// sched lock yet, so the garbage collector cannot be running.
+
+void runtime_entersyscall(void) __attribute__ ((no_split_stack));
+
+void
+runtime_entersyscall(void)
+{
+ uint32 v;
+
+ // Leave SP around for gc and traceback.
+#ifdef USING_SPLIT_STACK
+ g->gcstack = __splitstack_find(NULL, NULL, &g->gcstack_size,
+ &g->gcnext_segment, &g->gcnext_sp,
+ &g->gcinitial_sp);
+#else
+ g->gcnext_sp = (byte *) &v;
+#endif
+
+ // Save the registers in the g structure so that any pointers
+ // held in registers will be seen by the garbage collector.
+ // We could use getcontext here, but setjmp is more efficient
+ // because it doesn't need to save the signal mask.
+ setjmp(g->gcregs);
+
+ g->status = Gsyscall;
+
+ // Fast path.
+ // The slow path inside the schedlock/schedunlock will get
+ // through without stopping if it does:
+ // mcpu--
+ // gwait not true
+ // waitstop && mcpu <= mcpumax not true
+ // If we can do the same with a single atomic add,
+ // then we can skip the locks.
+ v = runtime_xadd(&runtime_sched.atomic, -1<<mcpuShift);
+ if(!atomic_gwaiting(v) && (!atomic_waitstop(v) || atomic_mcpu(v) > atomic_mcpumax(v)))
+ return;
+
+ schedlock();
+ v = runtime_atomicload(&runtime_sched.atomic);
+ if(atomic_gwaiting(v)) {
+ matchmg();
+ v = runtime_atomicload(&runtime_sched.atomic);
+ }
+ if(atomic_waitstop(v) && atomic_mcpu(v) <= atomic_mcpumax(v)) {
+ runtime_xadd(&runtime_sched.atomic, -1<<waitstopShift);
+ runtime_notewakeup(&runtime_sched.stopped);
+ }
+
+ schedunlock();
+}
+
+// The goroutine g exited its system call.
+// Arrange for it to run on a cpu again.
+// This is called only from the go syscall library, not
+// from the low-level system calls used by the runtime.
+void
+runtime_exitsyscall(void)
+{
+ G *gp;
+ uint32 v;
+
+ // Fast path.
+ // If we can do the mcpu++ bookkeeping and
+ // find that we still have mcpu <= mcpumax, then we can
+ // start executing Go code immediately, without having to
+ // schedlock/schedunlock.
+ gp = g;
+ v = runtime_xadd(&runtime_sched.atomic, (1<<mcpuShift));
+ if(m->profilehz == runtime_sched.profilehz && atomic_mcpu(v) <= atomic_mcpumax(v)) {
+ // There's a cpu for us, so we can run.
+ gp->status = Grunning;
+ // Garbage collector isn't running (since we are),
+ // so okay to clear gcstack.
+#ifdef USING_SPLIT_STACK
+ gp->gcstack = nil;
+#endif
+ gp->gcnext_sp = nil;
+ runtime_memclr(gp->gcregs, sizeof gp->gcregs);
+ return;
+ }
+
+ // Tell scheduler to put g back on the run queue:
+ // mostly equivalent to g->status = Grunning,
+ // but keeps the garbage collector from thinking
+ // that g is running right now, which it's not.
+ gp->readyonstop = 1;
+
+ // All the cpus are taken.
+ // The scheduler will ready g and put this m to sleep.
+ // When the scheduler takes g away from m,
+ // it will undo the runtime_sched.mcpu++ above.
+ runtime_gosched();
+
+ // Gosched returned, so we're allowed to run now.
+ // Delete the gcstack information that we left for
+ // the garbage collector during the system call.
+ // Must wait until now because until gosched returns
+ // we don't know for sure that the garbage collector
+ // is not running.
+#ifdef USING_SPLIT_STACK
+ gp->gcstack = nil;
+#endif
+ gp->gcnext_sp = nil;
+ runtime_memclr(gp->gcregs, sizeof gp->gcregs);
+}
+
+G*
+runtime_malg(int32 stacksize, byte** ret_stack, size_t* ret_stacksize)
+{
+ G *newg;
+
+ newg = runtime_malloc(sizeof(G));
+ if(stacksize >= 0) {
+#if USING_SPLIT_STACK
+ *ret_stack = __splitstack_makecontext(stacksize,
+ &newg->stack_context[0],
+ ret_stacksize);
+#else
+ *ret_stack = runtime_mallocgc(stacksize, FlagNoProfiling|FlagNoGC, 0, 0);
+ *ret_stacksize = stacksize;
+ newg->gcinitial_sp = *ret_stack;
+ newg->gcstack_size = stacksize;
+#endif
+ }
+ return newg;
+}
+
+G*
+__go_go(void (*fn)(void*), void* arg)
+{
+ byte *sp;
+ size_t spsize;
+ G * volatile newg; // volatile to avoid longjmp warning
+
+ schedlock();
+
+ if((newg = gfget()) != nil){
+#ifdef USING_SPLIT_STACK
+ sp = __splitstack_resetcontext(&newg->stack_context[0],
+ &spsize);
+#else
+ sp = newg->gcinitial_sp;
+ spsize = newg->gcstack_size;
+ newg->gcnext_sp = sp;
+#endif
+ } else {
+ newg = runtime_malg(StackMin, &sp, &spsize);
+ if(runtime_lastg == nil)
+ runtime_allg = newg;
+ else
+ runtime_lastg->alllink = newg;
+ runtime_lastg = newg;
+ }
+ newg->status = Gwaiting;
+ newg->waitreason = "new goroutine";
+
+ newg->entry = (byte*)fn;
+ newg->param = arg;
+ newg->gopc = (uintptr)__builtin_return_address(0);
+
+ runtime_sched.gcount++;
+ runtime_sched.goidgen++;
+ newg->goid = runtime_sched.goidgen;
+
+ if(sp == nil)
+ runtime_throw("nil g->stack0");
+
+ getcontext(&newg->context);
+ newg->context.uc_stack.ss_sp = sp;
+ newg->context.uc_stack.ss_size = spsize;
+ makecontext(&newg->context, kickoff, 0);
+
+ newprocreadylocked(newg);
+ schedunlock();
+
+ return newg;
+//printf(" goid=%d\n", newg->goid);
+}
+
+// Put on gfree list. Sched must be locked.
+static void
+gfput(G *g)
+{
+ g->schedlink = runtime_sched.gfree;
+ runtime_sched.gfree = g;
+}
+
+// Get from gfree list. Sched must be locked.
+static G*
+gfget(void)
+{
+ G *g;
+
+ g = runtime_sched.gfree;
+ if(g)
+ runtime_sched.gfree = g->schedlink;
+ return g;
+}
+
+// Run all deferred functions for the current goroutine.
+static void
+rundefer(void)
+{
+ Defer *d;
+
+ while((d = g->defer) != nil) {
+ void (*pfn)(void*);
+
+ pfn = d->__pfn;
+ d->__pfn = nil;
+ if (pfn != nil)
+ (*pfn)(d->__arg);
+ g->defer = d->__next;
+ runtime_free(d);
+ }
+}
+
+void runtime_Goexit (void) asm ("libgo_runtime.runtime.Goexit");
+
+void
+runtime_Goexit(void)
+{
+ rundefer();
+ runtime_goexit();
+}
+
+void runtime_Gosched (void) asm ("libgo_runtime.runtime.Gosched");
+
+void
+runtime_Gosched(void)
+{
+ runtime_gosched();
+}
+
+void runtime_LockOSThread (void)
+ __asm__ ("libgo_runtime.runtime.LockOSThread");
+
+void
+runtime_LockOSThread(void)
+{
+ m->lockedg = g;
+ g->lockedm = m;
+}
+
+// delete when scheduler is stronger
+int32
+runtime_gomaxprocsfunc(int32 n)
+{
+ int32 ret;
+ uint32 v;
+
+ schedlock();
+ ret = runtime_gomaxprocs;
+ if(n <= 0)
+ n = ret;
+ if(n > maxgomaxprocs)
+ n = maxgomaxprocs;
+ runtime_gomaxprocs = n;
+ if(runtime_gomaxprocs > 1)
+ runtime_singleproc = false;
+ if(runtime_gcwaiting != 0) {
+ if(atomic_mcpumax(runtime_sched.atomic) != 1)
+ runtime_throw("invalid mcpumax during gc");
+ schedunlock();
+ return ret;
+ }
+
+ setmcpumax(n);
+
+ // If there are now fewer allowed procs
+ // than procs running, stop.
+ v = runtime_atomicload(&runtime_sched.atomic);
+ if((int32)atomic_mcpu(v) > n) {
+ schedunlock();
+ runtime_gosched();
+ return ret;
+ }
+ // handle more procs
+ matchmg();
+ schedunlock();
+ return ret;
+}
+
+void runtime_UnlockOSThread (void)
+ __asm__ ("libgo_runtime.runtime.UnlockOSThread");
+
+void
+runtime_UnlockOSThread(void)
+{
+ m->lockedg = nil;
+ g->lockedm = nil;
+}
+
+bool
+runtime_lockedOSThread(void)
+{
+ return g->lockedm != nil && m->lockedg != nil;
+}
+
+// for testing of wire, unwire
+uint32
+runtime_mid()
+{
+ return m->id;
+}
+
+int32 runtime_Goroutines (void)
+ __asm__ ("libgo_runtime.runtime.Goroutines");
+
+int32
+runtime_Goroutines()
+{
+ return runtime_sched.gcount;
+}
+
+int32
+runtime_mcount(void)
+{
+ return runtime_sched.mcount;
+}
static struct {
Lock;
@@ -28,22 +1330,22 @@ static struct {
void
runtime_sigprof(uint8 *pc __attribute__ ((unused)),
uint8 *sp __attribute__ ((unused)),
- uint8 *lr __attribute__ ((unused)))
+ uint8 *lr __attribute__ ((unused)),
+ G *gp __attribute__ ((unused)))
{
- int32 n;
-
+ // int32 n;
+
if(prof.fn == nil || prof.hz == 0)
return;
-
+
runtime_lock(&prof);
if(prof.fn == nil) {
runtime_unlock(&prof);
return;
}
- n = 0;
- // n = runtime·gentraceback(pc, sp, lr, gp, 0, prof.pcbuf, nelem(prof.pcbuf));
- if(n > 0)
- prof.fn(prof.pcbuf, n);
+ // n = runtime_gentraceback(pc, sp, lr, gp, 0, prof.pcbuf, nelem(prof.pcbuf));
+ // if(n > 0)
+ // prof.fn(prof.pcbuf, n);
runtime_unlock(&prof);
}
@@ -67,28 +1369,10 @@ runtime_setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz)
prof.fn = fn;
prof.hz = hz;
runtime_unlock(&prof);
- // runtime_lock(&runtime_sched);
- // runtime_sched.profilehz = hz;
- // runtime_unlock(&runtime_sched);
-
+ runtime_lock(&runtime_sched);
+ runtime_sched.profilehz = hz;
+ runtime_unlock(&runtime_sched);
+
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.c b/libgo/runtime/runtime.c
new file mode 100644
index 00000000000..de4c982620f
--- /dev/null
+++ b/libgo/runtime/runtime.c
@@ -0,0 +1,172 @@
+// 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.
+
+#include <unistd.h>
+
+#include "runtime.h"
+#include "array.h"
+#include "go-panic.h"
+#include "go-string.h"
+
+uint32 runtime_panicking;
+
+static Lock paniclk;
+
+void
+runtime_startpanic(void)
+{
+ M *m;
+
+ m = runtime_m();
+ if(m->dying) {
+ runtime_printf("panic during panic\n");
+ runtime_exit(3);
+ }
+ m->dying = 1;
+ runtime_xadd(&runtime_panicking, 1);
+ runtime_lock(&paniclk);
+}
+
+void
+runtime_dopanic(int32 unused __attribute__ ((unused)))
+{
+ /*
+ static bool didothers;
+
+ if(g->sig != 0)
+ runtime_printf("[signal %x code=%p addr=%p pc=%p]\n",
+ g->sig, g->sigcode0, g->sigcode1, g->sigpc);
+
+ if(runtime_gotraceback()){
+ if(!didothers) {
+ didothers = true;
+ runtime_tracebackothers(g);
+ }
+ }
+ */
+
+ runtime_unlock(&paniclk);
+ if(runtime_xadd(&runtime_panicking, -1) != 0) {
+ // Some other m is panicking too.
+ // Let it print what it needs to print.
+ // Wait forever without chewing up cpu.
+ // It will exit when it's done.
+ static Lock deadlock;
+ runtime_lock(&deadlock);
+ runtime_lock(&deadlock);
+ }
+
+ runtime_exit(2);
+}
+
+void
+runtime_throw(const char *s)
+{
+ runtime_startpanic();
+ runtime_printf("throw: %s\n", s);
+ runtime_dopanic(0);
+ *(int32*)0 = 0; // not reached
+ runtime_exit(1); // even more not reached
+}
+
+static int32 argc;
+static byte** argv;
+
+extern Slice os_Args asm ("libgo_os.os.Args");
+extern Slice os_Envs asm ("libgo_os.os.Envs");
+
+void
+runtime_args(int32 c, byte **v)
+{
+ argc = c;
+ argv = v;
+}
+
+void
+runtime_goargs(void)
+{
+ String *s;
+ int32 i;
+
+ // for windows implementation see "os" package
+ if(Windows)
+ return;
+
+ s = runtime_malloc(argc*sizeof s[0]);
+ for(i=0; i<argc; i++)
+ s[i] = runtime_gostringnocopy((byte*)argv[i]);
+ os_Args.__values = (void*)s;
+ os_Args.__count = argc;
+ os_Args.__capacity = argc;
+}
+
+void
+runtime_goenvs(void)
+{
+ String *s;
+ int32 i, n;
+
+ for(n=0; argv[argc+1+n] != 0; n++)
+ ;
+
+ s = runtime_malloc(n*sizeof s[0]);
+ for(i=0; i<n; i++)
+ s[i] = runtime_gostringnocopy(argv[argc+1+i]);
+ os_Envs.__values = (void*)s;
+ os_Envs.__count = n;
+ os_Envs.__capacity = n;
+}
+
+const byte*
+runtime_getenv(const char *s)
+{
+ int32 i, j, len;
+ const byte *v, *bs;
+ String* envv;
+ int32 envc;
+
+ bs = (const byte*)s;
+ len = runtime_findnull(bs);
+ envv = (String*)os_Envs.__values;
+ envc = os_Envs.__count;
+ for(i=0; i<envc; i++){
+ if(envv[i].__length <= len)
+ continue;
+ v = (const byte*)envv[i].__data;
+ for(j=0; j<len; j++)
+ if(bs[j] != v[j])
+ goto nomatch;
+ if(v[len] != '=')
+ goto nomatch;
+ return v+len+1;
+ nomatch:;
+ }
+ return nil;
+}
+
+int32
+runtime_atoi(const byte *p)
+{
+ int32 n;
+
+ n = 0;
+ while('0' <= *p && *p <= '9')
+ n = n*10 + *p++ - '0';
+ return n;
+}
+
+uint32
+runtime_fastrand1(void)
+{
+ M *m;
+ uint32 x;
+
+ m = runtime_m();
+ x = m->fastrand;
+ x += x;
+ if(x & 0x80000000L)
+ x ^= 0x88888eefUL;
+ m->fastrand = x;
+ return x;
+}
diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h
index 7f061cbbe31..818465cb897 100644
--- a/libgo/runtime/runtime.h
+++ b/libgo/runtime/runtime.h
@@ -8,6 +8,7 @@
#define _GNU_SOURCE
#include "go-assert.h"
+#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -17,17 +18,17 @@
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
+#include <ucontext.h>
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
+#include "array.h"
#include "go-alloc.h"
#include "go-panic.h"
#include "go-string.h"
-typedef struct __go_string String;
-
/* This file supports C files copied from the 6g runtime library.
This is a version of the 6g runtime.h rewritten for gccgo's version
of the code. */
@@ -49,69 +50,82 @@ typedef unsigned int uintptr __attribute__ ((mode (pointer)));
typedef uint8 bool;
typedef uint8 byte;
typedef struct G G;
+typedef union Lock Lock;
typedef struct M M;
+typedef union Note Note;
typedef struct MCache MCache;
typedef struct FixAlloc FixAlloc;
-typedef struct Lock Lock;
typedef struct __go_defer_stack Defer;
typedef struct __go_panic_stack Panic;
+typedef struct __go_open_array Slice;
+typedef struct __go_string String;
-/* We use mutexes for locks. 6g uses futexes directly, and perhaps
- someday we will do that too. */
-
-struct Lock
-{
- uint32 key;
- sem_t sem;
-};
-
-/* A Note. */
-
-typedef struct Note Note;
-
-struct Note {
- int32 woken;
-};
-
-/* Per CPU declarations. */
-
-#ifdef __rtems__
-#define __thread
-#endif
-
-extern __thread G* g;
-extern __thread M* m;
+/*
+ * per-cpu declaration.
+ */
+extern M* runtime_m(void);
+extern G* runtime_g(void);
extern M runtime_m0;
extern G runtime_g0;
-#ifdef __rtems__
-#undef __thread
-#endif
-
-/* Constants. */
-
+/*
+ * defined constants
+ */
+enum
+{
+ // G status
+ //
+ // If you add to this list, add to the list
+ // of "okay during garbage collection" status
+ // in mgc0.c too.
+ Gidle,
+ Grunnable,
+ Grunning,
+ Gsyscall,
+ Gwaiting,
+ Gmoribund,
+ Gdead,
+};
enum
{
true = 1,
false = 0,
};
-/* Structures. */
-
+/*
+ * structures
+ */
+union Lock
+{
+ uint32 key; // futex-based impl
+ M* waitm; // linked list of waiting M's (sema-based impl)
+};
+union Note
+{
+ uint32 key; // futex-based impl
+ M* waitm; // waiting M (sema-based impl)
+};
struct G
{
Defer* defer;
Panic* panic;
void* exception; // current exception being thrown
bool is_foreign; // whether current exception from other language
+ void *gcstack; // if status==Gsyscall, gcstack = stackbase to use during gc
+ uintptr gcstack_size;
+ void* gcnext_segment;
+ void* gcnext_sp;
+ void* gcinitial_sp;
+ jmp_buf gcregs;
byte* entry; // initial function
G* alllink; // on allg
void* param; // passed parameter on wakeup
+ bool fromgogo; // reached from gogo
int16 status;
int32 goid;
- int8* waitreason; // if status==Gwaiting
+ const char* waitreason; // if status==Gwaiting
G* schedlink;
bool readyonstop;
bool ispanic;
@@ -122,85 +136,144 @@ struct G
// uintptr sigcode0;
// uintptr sigcode1;
// uintptr sigpc;
- // uintptr gopc; // pc of go statement that created this goroutine
+ uintptr gopc; // pc of go statement that created this goroutine
+
+ ucontext_t context;
+ void* stack_context[10];
};
struct M
{
+ G* g0; // goroutine with scheduling stack
+ G* gsignal; // signal-handling G
G* curg; // current running goroutine
int32 id;
int32 mallocing;
int32 gcing;
int32 locks;
int32 nomemprof;
- int32 gcing_for_prof;
- int32 holds_finlock;
- int32 gcing_for_finlock;
+ int32 waitnextg;
+ int32 dying;
int32 profilehz;
+ int32 helpgc;
uint32 fastrand;
+ Note havenextg;
+ G* nextg;
+ M* alllink; // on allm
+ M* schedlink;
MCache *mcache;
+ G* lockedg;
+ G* idleg;
+ M* nextwaitm; // next M waiting for lock
+ uintptr waitsema; // semaphore for parking on locks
+ uint32 waitsemacount;
+ uint32 waitsemalock;
+};
- /* For the list of all threads. */
- struct __go_thread_id *list_entry;
+/* Macros. */
- /* For the garbage collector. */
- void *gc_sp;
- size_t gc_len;
- void *gc_next_segment;
- void *gc_next_sp;
- void *gc_initial_sp;
+#ifdef __WINDOWS__
+enum {
+ Windows = 1
+};
+#else
+enum {
+ Windows = 0
};
+#endif
-/* Macros. */
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
#define nil ((void*)0)
#define USED(v) ((void) v)
-/* We map throw to assert. */
-#define runtime_throw(s) __go_assert(s == 0)
+/*
+ * external data
+ */
+G* runtime_allg;
+G* runtime_lastg;
+M* runtime_allm;
+extern int32 runtime_gomaxprocs;
+extern bool runtime_singleproc;
+extern uint32 runtime_panicking;
+extern int32 runtime_gcwaiting; // gc is waiting to run
+int32 runtime_ncpu;
+/*
+ * common functions and data
+ */
+int32 runtime_findnull(const byte*);
+
+/*
+ * very low level c-called
+ */
+void runtime_args(int32, byte**);
+void runtime_osinit();
+void runtime_goargs(void);
+void runtime_goenvs(void);
+void runtime_throw(const char*);
void* runtime_mal(uintptr);
+void runtime_schedinit(void);
+void runtime_initsig(int32);
+String runtime_gostringnocopy(byte*);
+void* runtime_mstart(void*);
+G* runtime_malg(int32, byte**, size_t*);
+void runtime_minit(void);
void runtime_mallocinit(void);
-void runtime_initfintab(void);
+void runtime_gosched(void);
+void runtime_goexit(void);
+void runtime_entersyscall(void) __asm__("libgo_syscall.syscall.entersyscall");
+void runtime_exitsyscall(void) __asm__("libgo_syscall.syscall.exitsyscall");
void siginit(void);
bool __go_sigsend(int32 sig);
int64 runtime_nanotime(void);
void runtime_stoptheworld(void);
void runtime_starttheworld(bool);
-void __go_go(void (*pfn)(void*), void*);
-void __go_gc_goroutine_init(void*);
-void __go_enable_gc(void);
-int __go_run_goroutine_gc(int);
-void __go_scanstacks(void (*scan)(byte *, int64));
-void __go_stealcache(void);
-void __go_cachestats(void);
+G* __go_go(void (*pfn)(void*), void*);
/*
* mutual exclusion locks. in the uncontended case,
* as fast as spin locks (just a few user-level instructions),
* but on the contention path they sleep in the kernel.
+ * a zeroed Lock is unlocked (no need to initialize each lock).
*/
-void runtime_initlock(Lock*);
void runtime_lock(Lock*);
void runtime_unlock(Lock*);
-void runtime_destroylock(Lock*);
-
-void runtime_semacquire (uint32 *) asm ("libgo_runtime.runtime.Semacquire");
-void runtime_semrelease (uint32 *) asm ("libgo_runtime.runtime.Semrelease");
/*
* sleep and wakeup on one-time events.
* before any calls to notesleep or notewakeup,
* must call noteclear to initialize the Note.
- * then, any number of threads can call notesleep
+ * then, exactly one thread can call notesleep
* and exactly one thread can call notewakeup (once).
- * once notewakeup has been called, all the notesleeps
- * will return. future notesleeps will return immediately.
+ * once notewakeup has been called, the notesleep
+ * will return. future notesleep will return immediately.
+ * subsequent noteclear must be called only after
+ * previous notesleep has returned, e.g. it's disallowed
+ * to call noteclear straight after notewakeup.
+ *
+ * notetsleep is like notesleep but wakes up after
+ * a given number of nanoseconds even if the event
+ * has not yet happened. if a goroutine uses notetsleep to
+ * wake up early, it must wait to call noteclear until it
+ * can be sure that no other goroutine is calling
+ * notewakeup.
*/
void runtime_noteclear(Note*);
void runtime_notesleep(Note*);
void runtime_notewakeup(Note*);
+void runtime_notetsleep(Note*, int64);
+
+/*
+ * low-level synchronization for implementing the above
+ */
+uintptr runtime_semacreate(void);
+int32 runtime_semasleep(int64);
+void runtime_semawakeup(M*);
+// or
+void runtime_futexsleep(uint32*, uint32, int64);
+void runtime_futexwakeup(uint32*, uint32);
+
/* Functions. */
#define runtime_printf printf
@@ -208,10 +281,9 @@ void runtime_notewakeup(Note*);
#define runtime_free(p) __go_free(p)
#define runtime_memclr(buf, size) __builtin_memset((buf), 0, (size))
#define runtime_strcmp(s1, s2) __builtin_strcmp((s1), (s2))
-#define runtime_getenv(s) getenv(s)
-#define runtime_atoi(s) atoi(s)
#define runtime_mcmp(a, b, s) __builtin_memcmp((a), (b), (s))
#define runtime_memmove(a, b, s) __builtin_memmove((a), (b), (s))
+#define runtime_exit(s) _exit(s)
MCache* runtime_allocmcache(void);
void free(void *v);
struct __go_func_type;
@@ -221,12 +293,24 @@ bool runtime_addfinalizer(void*, void(*fn)(void*), const struct __go_func_type *
#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);
+#define runtime_xchg(p, v) __atomic_exchange_n (p, v, __ATOMIC_SEQ_CST)
+#define runtime_atomicload(p) __atomic_load_n (p, __ATOMIC_SEQ_CST)
+#define runtime_atomicstore(p, v) __atomic_store_n (p, v, __ATOMIC_SEQ_CST)
+#define runtime_atomicloadp(p) __atomic_load_n (p, __ATOMIC_SEQ_CST)
+#define runtime_atomicstorep(p, v) __atomic_store_n (p, v, __ATOMIC_SEQ_CST)
+
+void runtime_dopanic(int32) __attribute__ ((noreturn));
+void runtime_startpanic(void);
+void runtime_ready(G*);
+const byte* runtime_getenv(const char*);
+int32 runtime_atoi(const byte*);
+void runtime_sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp);
void runtime_resetcpuprofiler(int32);
void runtime_setcpuprofilerate(void(*)(uintptr*, int32), int32);
uint32 runtime_fastrand1(void);
+void runtime_semacquire(uint32 volatile *);
+void runtime_semrelease(uint32 volatile *);
+int32 runtime_gomaxprocsfunc(int32 n);
void runtime_procyield(uint32);
void runtime_osyield(void);
void runtime_usleep(uint32);
@@ -239,3 +323,6 @@ void reflect_call(const struct __go_func_type *, const void *, _Bool, _Bool,
#ifdef __rtems__
void __wrap_rtems_task_variable_add(void **);
#endif
+
+/* Temporary. */
+void runtime_cond_wait(pthread_cond_t*, pthread_mutex_t*);
diff --git a/libgo/runtime/runtime1.goc b/libgo/runtime/runtime1.goc
new file mode 100644
index 00000000000..4cd98041717
--- /dev/null
+++ b/libgo/runtime/runtime1.goc
@@ -0,0 +1,10 @@
+// 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 runtime
+#include "runtime.h"
+
+func GOMAXPROCS(n int32) (ret int32) {
+ ret = runtime_gomaxprocsfunc(n);
+}
diff --git a/libgo/runtime/sema.goc b/libgo/runtime/sema.goc
new file mode 100644
index 00000000000..dd58cf38fb8
--- /dev/null
+++ b/libgo/runtime/sema.goc
@@ -0,0 +1,181 @@
+// 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.
+
+// Semaphore implementation exposed to Go.
+// Intended use is provide a sleep and wakeup
+// primitive that can be used in the contended case
+// of other synchronization primitives.
+// Thus it targets the same goal as Linux's futex,
+// but it has much simpler semantics.
+//
+// That is, don't think of these as semaphores.
+// Think of them as a way to implement sleep and wakeup
+// such that every sleep is paired with a single wakeup,
+// even if, due to races, the wakeup happens before the sleep.
+//
+// See Mullender and Cox, ``Semaphores in Plan 9,''
+// http://swtch.com/semaphore.pdf
+
+package runtime
+#include "runtime.h"
+#include "arch.h"
+
+typedef struct Sema Sema;
+struct Sema
+{
+ uint32 volatile *addr;
+ G *g;
+ Sema *prev;
+ Sema *next;
+};
+
+typedef struct SemaRoot SemaRoot;
+struct SemaRoot
+{
+ Lock;
+ Sema *head;
+ Sema *tail;
+ // Number of waiters. Read w/o the lock.
+ uint32 volatile nwait;
+};
+
+// Prime to not correlate with any user patterns.
+#define SEMTABLESZ 251
+
+static union
+{
+ SemaRoot;
+ uint8 pad[CacheLineSize];
+} semtable[SEMTABLESZ];
+
+static SemaRoot*
+semroot(uint32 volatile *addr)
+{
+ return &semtable[((uintptr)addr >> 3) % SEMTABLESZ];
+}
+
+static void
+semqueue(SemaRoot *root, uint32 volatile *addr, Sema *s)
+{
+ s->g = runtime_g();
+ s->addr = addr;
+ s->next = nil;
+ s->prev = root->tail;
+ if(root->tail)
+ root->tail->next = s;
+ else
+ root->head = s;
+ root->tail = s;
+}
+
+static void
+semdequeue(SemaRoot *root, Sema *s)
+{
+ if(s->next)
+ s->next->prev = s->prev;
+ else
+ root->tail = s->prev;
+ if(s->prev)
+ s->prev->next = s->next;
+ else
+ root->head = s->next;
+ s->prev = nil;
+ s->next = nil;
+}
+
+static int32
+cansemacquire(uint32 volatile *addr)
+{
+ uint32 v;
+
+ while((v = runtime_atomicload(addr)) > 0)
+ if(runtime_cas(addr, v, v-1))
+ return 1;
+ return 0;
+}
+
+void
+runtime_semacquire(uint32 volatile *addr)
+{
+ G *g;
+ Sema s;
+ SemaRoot *root;
+
+ // Easy case.
+ if(cansemacquire(addr))
+ return;
+
+ // Harder case:
+ // increment waiter count
+ // try cansemacquire one more time, return if succeeded
+ // enqueue itself as a waiter
+ // sleep
+ // (waiter descriptor is dequeued by signaler)
+ g = runtime_g();
+ root = semroot(addr);
+ for(;;) {
+
+ runtime_lock(root);
+ // Add ourselves to nwait to disable "easy case" in semrelease.
+ runtime_xadd(&root->nwait, 1);
+ // Check cansemacquire to avoid missed wakeup.
+ if(cansemacquire(addr)) {
+ runtime_xadd(&root->nwait, -1);
+ runtime_unlock(root);
+ return;
+ }
+ // Any semrelease after the cansemacquire knows we're waiting
+ // (we set nwait above), so go to sleep.
+ semqueue(root, addr, &s);
+ g->status = Gwaiting;
+ g->waitreason = "semacquire";
+ runtime_unlock(root);
+ runtime_gosched();
+ if(cansemacquire(addr))
+ return;
+ }
+}
+
+void
+runtime_semrelease(uint32 volatile *addr)
+{
+ Sema *s;
+ SemaRoot *root;
+
+ root = semroot(addr);
+ runtime_xadd(addr, 1);
+
+ // Easy case: no waiters?
+ // This check must happen after the xadd, to avoid a missed wakeup
+ // (see loop in semacquire).
+ if(runtime_atomicload(&root->nwait) == 0)
+ return;
+
+ // Harder case: search for a waiter and wake it.
+ runtime_lock(root);
+ if(runtime_atomicload(&root->nwait) == 0) {
+ // The count is already consumed by another goroutine,
+ // so no need to wake up another goroutine.
+ runtime_unlock(root);
+ return;
+ }
+ for(s = root->head; s; s = s->next) {
+ if(s->addr == addr) {
+ runtime_xadd(&root->nwait, -1);
+ semdequeue(root, s);
+ break;
+ }
+ }
+ runtime_unlock(root);
+ if(s)
+ runtime_ready(s->g);
+}
+
+func Semacquire(addr *uint32) {
+ runtime_semacquire(addr);
+}
+
+func Semrelease(addr *uint32) {
+ runtime_semrelease(addr);
+}
diff --git a/libgo/runtime/sigqueue.goc b/libgo/runtime/sigqueue.goc
index 3a908680ece..502dc442c83 100644
--- a/libgo/runtime/sigqueue.goc
+++ b/libgo/runtime/sigqueue.goc
@@ -81,9 +81,9 @@ __go_sigsend(int32 s)
// Called to receive a bitmask of queued signals.
func Sigrecv() (m uint32) {
- // runtime·entersyscall();
+ runtime_entersyscall();
runtime_notesleep(&sig);
- // runtime·exitsyscall();
+ runtime_exitsyscall();
runtime_noteclear(&sig);
for(;;) {
m = sig.mask;
@@ -110,5 +110,6 @@ func Signame(sig int32) (name String) {
}
func Siginit() {
+ runtime_initsig(1);
sig.inuse = true; // enable reception of signals; cannot disable
}
diff --git a/libgo/runtime/string.goc b/libgo/runtime/string.goc
index 332277c52e2..aa75628730e 100644
--- a/libgo/runtime/string.goc
+++ b/libgo/runtime/string.goc
@@ -6,6 +6,24 @@ package runtime
#include "runtime.h"
#define charntorune(pv, str, len) __go_get_rune(str, len, pv)
+int32
+runtime_findnull(const byte *s)
+{
+ if(s == nil)
+ return 0;
+ return __builtin_strlen((const char*) s);
+}
+
+String
+runtime_gostringnocopy(byte *str)
+{
+ String s;
+
+ s.__data = (const unsigned char *) str;
+ s.__length = runtime_findnull(str);
+ return s;
+}
+
enum
{
Runeself = 0x80,
diff --git a/libgo/runtime/thread-linux.c b/libgo/runtime/thread-linux.c
new file mode 100644
index 00000000000..b51f4970d25
--- /dev/null
+++ b/libgo/runtime/thread-linux.c
@@ -0,0 +1,101 @@
+// 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.
+
+#include "runtime.h"
+
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <syscall.h>
+#include <linux/futex.h>
+
+typedef struct timespec Timespec;
+
+// Atomically,
+// if(*addr == val) sleep
+// Might be woken up spuriously; that's allowed.
+// Don't sleep longer than ns; ns < 0 means forever.
+void
+runtime_futexsleep(uint32 *addr, uint32 val, int64 ns)
+{
+ Timespec ts, *tsp;
+
+ if(ns < 0)
+ tsp = nil;
+ else {
+ ts.tv_sec = ns/1000000000LL;
+ ts.tv_nsec = ns%1000000000LL;
+ // Avoid overflowdefs
+ if(ts.tv_sec > 1<<30)
+ ts.tv_sec = 1<<30;
+ tsp = &ts;
+ }
+
+ // Some Linux kernels have a bug where futex of
+ // FUTEX_WAIT returns an internal error code
+ // as an errno. Libpthread ignores the return value
+ // here, and so can we: as it says a few lines up,
+ // spurious wakeups are allowed.
+ syscall(__NR_futex, addr, FUTEX_WAIT, val, tsp, nil, 0);
+}
+
+// If any procs are sleeping on addr, wake up at most cnt.
+void
+runtime_futexwakeup(uint32 *addr, uint32 cnt)
+{
+ int64 ret;
+
+ ret = syscall(__NR_futex, addr, FUTEX_WAKE, cnt, nil, nil, 0);
+
+ if(ret >= 0)
+ return;
+
+ // I don't know that futex wakeup can return
+ // EAGAIN or EINTR, but if it does, it would be
+ // safe to loop and call futex again.
+ runtime_printf("futexwakeup addr=%p returned %lld\n", addr, (long long)ret);
+ *(int32*)0x1006 = 0x1006;
+}
+
+static int32
+getproccount(void)
+{
+ int32 fd, rd, cnt, cpustrlen;
+ const char *cpustr;
+ const byte *pos;
+ byte *bufpos;
+ byte buf[256];
+
+ fd = open("/proc/stat", O_RDONLY|O_CLOEXEC, 0);
+ if(fd == -1)
+ return 1;
+ cnt = 0;
+ bufpos = buf;
+ cpustr = "\ncpu";
+ cpustrlen = strlen(cpustr);
+ for(;;) {
+ rd = read(fd, bufpos, sizeof(buf)-cpustrlen);
+ if(rd == -1)
+ break;
+ bufpos[rd] = 0;
+ for(pos=buf; (pos=(const byte*)strstr((const char*)pos, cpustr)) != nil; cnt++, pos++) {
+ }
+ if(rd < cpustrlen)
+ break;
+ memmove(buf, bufpos+rd-cpustrlen+1, cpustrlen-1);
+ bufpos = buf+cpustrlen-1;
+ }
+ close(fd);
+ return cnt ? cnt : 1;
+}
+
+void
+runtime_osinit(void)
+{
+ runtime_ncpu = getproccount();
+}
diff --git a/libgo/runtime/thread-sema.c b/libgo/runtime/thread-sema.c
new file mode 100644
index 00000000000..b0a6dc337fd
--- /dev/null
+++ b/libgo/runtime/thread-sema.c
@@ -0,0 +1,74 @@
+// 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.
+
+#include "runtime.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <semaphore.h>
+
+/* Create a semaphore. */
+
+uintptr
+runtime_semacreate(void)
+{
+ sem_t *p;
+
+ /* Call malloc rather than runtime_malloc. This will allocate space
+ on the C heap. We can't call runtime_malloc here because it
+ could cause a deadlock. */
+ p = malloc (sizeof (sem_t));
+ if (sem_init (p, 0, 0) != 0)
+ runtime_throw ("sem_init");
+ return (uintptr) p;
+}
+
+/* Acquire m->waitsema. */
+
+int32
+runtime_semasleep (int64 ns)
+{
+ int r;
+
+ if (ns >= 0)
+ {
+ struct timespec ts;
+
+ ns += runtime_nanotime ();
+ ts.tv_sec = ns / 1000000000LL;
+ ts.tv_nsec = ns % 1000000000LL;
+ r = sem_timedwait ((sem_t *) m->waitsema, &ts);
+ if (r != 0)
+ {
+ if (errno == ETIMEDOUT || errno == EINTR)
+ return -1;
+ runtime_throw ("sema_timedwait");
+ }
+ return 0;
+ }
+
+ while (sem_wait ((sem_t *) m->waitsema) != 0)
+ {
+ if (errno == EINTR)
+ continue;
+ runtime_throw ("sem_wait");
+ }
+
+ return 0;
+}
+
+/* Wake up mp->waitsema. */
+
+void
+runtime_semawakeup (M *mp)
+{
+ if (sem_post ((sem_t *) mp->waitsema) != 0)
+ runtime_throw ("sem_post");
+}
+
+void
+runtime_osinit(void)
+{
+}
diff --git a/libgo/runtime/thread.c b/libgo/runtime/thread.c
index 822d5da0cac..459fc85c780 100644
--- a/libgo/runtime/thread.c
+++ b/libgo/runtime/thread.c
@@ -3,103 +3,114 @@
// license that can be found in the LICENSE file.
#include <errno.h>
+#include <signal.h>
+
#include "runtime.h"
#include "go-assert.h"
-void
-runtime_initlock(Lock *l)
-{
- l->key = 0;
- if(sem_init(&l->sem, 0, 0) != 0)
- runtime_throw("sem_init failed");
-}
+/* For targets which don't have the required sync support. Really
+ these should be provided by gcc itself. FIXME. */
-// noinline so that runtime_lock doesn't have to split the stack.
-static void runtime_lock_full(Lock *l) __attribute__ ((noinline));
+#if !defined (HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4) || !defined (HAVE_SYNC_FETCH_AND_ADD_4)
-static void
-runtime_lock_full(Lock *l)
-{
- for(;;){
- if(sem_wait(&l->sem) == 0)
- return;
- if(errno != EINTR)
- runtime_throw("sem_wait failed");
- }
-}
+static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER;
-void
-runtime_lock(Lock *l)
-{
- if(m != nil) {
- if(m->locks < 0)
- runtime_throw("lock count");
- m->locks++;
- }
-
- if(runtime_xadd(&l->key, 1) > 1) // someone else has it; wait
- runtime_lock_full(l);
-}
+#endif
-static void runtime_unlock_full(Lock *l) __attribute__ ((noinline));
+#ifndef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4
-static void
-runtime_unlock_full(Lock *l)
-{
- if(sem_post(&l->sem) != 0)
- runtime_throw("sem_post failed");
-}
+_Bool
+__sync_bool_compare_and_swap_4 (uint32*, uint32, uint32)
+ __attribute__ ((visibility ("hidden")));
-void
-runtime_unlock(Lock *l)
+_Bool
+__sync_bool_compare_and_swap_4 (uint32* ptr, uint32 old, uint32 new)
{
- if(m != nil) {
- m->locks--;
- if(m->locks < 0)
- runtime_throw("lock count");
- }
-
- if(runtime_xadd(&l->key, -1) > 0) // someone else is waiting
- runtime_unlock_full(l);
-}
+ int i;
+ _Bool ret;
-void
-runtime_destroylock(Lock *l)
-{
- sem_destroy(&l->sem);
-}
+ i = pthread_mutex_lock (&sync_lock);
+ __go_assert (i == 0);
-#ifndef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4
+ if (*ptr != old)
+ ret = 0;
+ else
+ {
+ *ptr = new;
+ ret = 1;
+ }
-// For targets which don't have the required sync support. Really
-// this should be provided by gcc itself. FIXME.
+ i = pthread_mutex_unlock (&sync_lock);
+ __go_assert (i == 0);
-static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER;
+ return ret;
+}
-_Bool
-__sync_bool_compare_and_swap_4(uint32*, uint32, uint32)
- __attribute__((visibility("hidden")));
+#endif
-_Bool
-__sync_bool_compare_and_swap_4(uint32* ptr, uint32 old, uint32 new)
+#ifndef HAVE_SYNC_FETCH_AND_ADD_4
+
+uint32
+__sync_fetch_and_add_4 (uint32*, uint32)
+ __attribute__ ((visibility ("hidden")));
+
+uint32
+__sync_fetch_and_add_4 (uint32* ptr, uint32 add)
{
int i;
- _Bool ret;
+ uint32 ret;
- i = pthread_mutex_lock(&sync_lock);
- __go_assert(i == 0);
+ i = pthread_mutex_lock (&sync_lock);
+ __go_assert (i == 0);
- if(*ptr != old) {
- ret = 0;
- } else {
- *ptr = new;
- ret = 1;
- }
+ ret = *ptr;
+ *ptr += add;
- i = pthread_mutex_unlock(&sync_lock);
- __go_assert(i == 0);
+ i = pthread_mutex_unlock (&sync_lock);
+ __go_assert (i == 0);
return ret;
}
#endif
+
+// Called to initialize a new m (including the bootstrap m).
+void
+runtime_minit(void)
+{
+ byte* stack;
+ size_t stacksize;
+ stack_t ss;
+
+ // Initialize signal handling.
+ runtime_m()->gsignal = runtime_malg(32*1024, &stack, &stacksize); // OS X wants >=8K, Linux >=2K
+ ss.ss_sp = stack;
+ ss.ss_flags = 0;
+ ss.ss_size = stacksize;
+ if(sigaltstack(&ss, nil) < 0)
+ *(int *)0xf1 = 0xf1;
+}
+
+// Temporary functions, which will be removed when we stop using
+// condition variables.
+
+void
+runtime_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex)
+{
+ int i;
+
+ runtime_entersyscall();
+
+ i = pthread_cond_wait(cond, mutex);
+ if(i != 0)
+ runtime_throw("pthread_cond_wait");
+ i = pthread_mutex_unlock(mutex);
+ if(i != 0)
+ runtime_throw("pthread_mutex_unlock");
+
+ runtime_exitsyscall();
+
+ i = pthread_mutex_lock(mutex);
+ if(i != 0)
+ runtime_throw("pthread_mutex_lock");
+}
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index 6858636c1ab..b52de1a1aea 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,7 @@
+2011-11-21 Andreas Tobler <andreast@fgznet.ch>
+
+ * configure: Regenerate.
+
2011-10-10 Matthias Klose <doko@ubuntu.com>
* config/posix95: Remove empty directory.
diff --git a/libgomp/configure b/libgomp/configure
index 50dc29a6201..6f25c6f5eb9 100755
--- a/libgomp/configure
+++ b/libgomp/configure
@@ -9317,7 +9317,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct=yes
hardcode_minus_L=yes
@@ -10230,7 +10230,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -10248,7 +10248,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
@@ -13164,7 +13164,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
archive_cmds_FC='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct_FC=yes
hardcode_minus_L_FC=yes
@@ -13869,7 +13869,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -13887,7 +13887,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
diff --git a/libitm/ChangeLog b/libitm/ChangeLog
index 46c984e8c75..be994a5c36e 100644
--- a/libitm/ChangeLog
+++ b/libitm/ChangeLog
@@ -1,3 +1,75 @@
+2011-11-23 Iain Sandoe <iains@gcc.gnu.org>
+
+ * Makefile.am (libitm_la_LDFLAGS): Remove "-no-undefined".
+ * Makefile.in: Regenerate.
+
+2011-11-22 Iain Sandoe <iains@gcc.gnu.org>
+
+ * configure.ac: Use GCC_CHECK_ELF_STYLE_WEAKREF.
+ * alloc_cpp.cc: Generate dummy functions if we don't
+ HAVE_ELF_STYLE_WEAKREF.
+ * eh_cpp.cc: Likewise.
+ * configure: Regenerate.
+ * aclocal.m4: Likewise.
+ * config.h.in: Likewise.
+ * Makefile.in: Likewise.
+ * testsuite/Makefile.in: Likewise.
+
+2011-11-22 Iain Sandoe <iains@gcc.gnu.org>
+
+ * config/x86/sjlj.S (CONCAT1, CONCAT2, SYM): Respond to
+ __USER_LABEL_PREFIX__ for targets that use it.
+ (TYPE, SIZE, HIDDEN): New macros to assist on non-elf targets.
+ (_ITM_beginTransaction): Use SYM, TYPE, SIZE macros to assist
+ in portability to non-elf targets.
+ (GTM_longjmp): Likewise.
+ * libitm_i.h (begin_transaction): Apply __USER_LABEL_PREFIX__
+ where required.
+
+2011-11-22 Iain Sandoe <iains@gcc.gnu.org>
+
+ * testsuite/libitm.c/memcpy-1.c: Allow for MAP_ANON spelling.
+ * testsuite/libitm.c/memset-1.c: Likewise.
+
+2011-11-21 Andreas Tobler <andreast@fgznet.ch>
+
+ * configure: Regenerate.
+
+2011-11-21 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * acinclude.m4 (LIBITM_CHECK_LINKER_FEATURES): Handle gold.
+ (LIBITM_ENABLE_SYMVERS): Handle sun style.
+ * Makefile.am: Handle sun style versioning.
+ (libitm_la_LINK): Add $(libitm_la_LDFLAGS).
+ * configure: Regenerate.
+ * Makefile.in: Regenerate.
+
+2011-11-18 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * config/generic/asmcfi.h: Fix comment.
+ * config/x86/sjlj.S (_ITM_beginTransaction): Provide ELF PIC code
+ sequence without .hidden support, error for non-ELF targets.
+ (GTM_longjmp) [__ELF__]: Only use .hidden if
+ HAVE_ATTRIBUTE_VISIBILITY.
+
+2011-11-17 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * alloc_cpp.cc [__osf__] (_ZnwX, _ZdlPv, _ZnaX, _ZdaPv,
+ _ZnwXRKSt9nothrow_t, _ZdlPvRKSt9nothrow_t, _ZdaPvRKSt9nothrow_t):
+ Dummy functions.
+ * eh_cpp.cc [__osf__] (__cxa_allocate_exception, __cxa_throw,
+ __cxa_begin_catch, __cxa_end_catch, __cxa_tm_cleanup): Likewise.
+
+2011-11-16 Uros Bizjak <ubizjak@gmail.com>
+
+ PR bootstrap/51098
+ * acinclude.m4 (LIBITM_CHECK_AS_AVX): Fix target selector.
+ * configure: Regenerate.
+
+2011-11-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ * testsuite/lib/libitm.exp: Check ia32 instead of ilp32.
+
2011-11-10 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* config/alpha/sjlj.S (_ITM_beginTransaction) [!__ELF__]: Don't use
diff --git a/libitm/Makefile.am b/libitm/Makefile.am
index b4674a572fc..26e1ebc632c 100644
--- a/libitm/Makefile.am
+++ b/libitm/Makefile.am
@@ -27,17 +27,34 @@ toolexeclib_LTLIBRARIES = libitm.la
nodist_toolexeclib_HEADERS = libitm.spec
if LIBITM_BUILD_VERSIONED_SHLIB
+if LIBITM_BUILD_VERSIONED_SHLIB_GNU
libitm_version_script = -Wl,--version-script,$(top_srcdir)/libitm.map
+libitm_version_dep = $(top_srcdir)/libitm.map
+endif
+if LIBITM_BUILD_VERSIONED_SHLIB_SUN
+libitm_version_script = -Wl,-M,libitm.map-sun
+libitm_version_dep = libitm.map-sun
+libitm.map-sun : $(top_srcdir)/libitm.map \
+ $(top_srcdir)/../contrib/make_sunver.pl \
+ $(libitm_la_OBJECTS) $(libitm_la_LIBADD)
+ perl $(top_srcdir)/../contrib/make_sunver.pl \
+ $(top_srcdir)/libitm.map \
+ $(libitm_la_OBJECTS:%.lo=.libs/%.o) \
+ `echo $(libitm_la_LIBADD) | \
+ sed 's,/\([^/.]*\)\.la,/.libs/\1.a,g'` \
+ > $@ || (rm -f $@ ; exit 1)
+endif
else
libitm_version_script =
+libitm_version_dep =
endif
libitm_version_info = -version-info $(libtool_VERSION)
# Force link with C, not C++. For now, while we're using C++ we don't
# want or need libstdc++.
-libitm_la_LINK = $(LINK)
-libitm_la_LDFLAGS = $(libitm_version_info) $(libitm_version_script) \
- -no-undefined
+libitm_la_DEPENDENCIES = $(libitm_version_dep)
+libitm_la_LINK = $(LINK) $(libitm_la_LDFLAGS)
+libitm_la_LDFLAGS = $(libitm_version_info) $(libitm_version_script)
libitm_la_SOURCES = \
aatree.cc alloc.cc alloc_c.cc alloc_cpp.cc barrier.cc beginend.cc \
diff --git a/libitm/Makefile.in b/libitm/Makefile.in
index 74261463ebf..dc7738275e8 100644
--- a/libitm/Makefile.in
+++ b/libitm/Makefile.in
@@ -57,10 +57,12 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
$(top_srcdir)/../config/multi.m4 \
$(top_srcdir)/../config/override.m4 \
$(top_srcdir)/../config/stdint.m4 \
- $(top_srcdir)/../config/tls.m4 $(top_srcdir)/../ltoptions.m4 \
- $(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \
- $(top_srcdir)/../lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
- $(top_srcdir)/../libtool.m4 $(top_srcdir)/configure.ac
+ $(top_srcdir)/../config/tls.m4 \
+ $(top_srcdir)/../config/weakref.m4 \
+ $(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
+ $(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/../libtool.m4 \
+ $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
@@ -359,15 +361,18 @@ AM_LDFLAGS = $(XLDFLAGS) $(SECTION_LDFLAGS) $(OPT_LDFLAGS)
toolexeclib_LTLIBRARIES = libitm.la
nodist_toolexeclib_HEADERS = libitm.spec
@LIBITM_BUILD_VERSIONED_SHLIB_FALSE@libitm_version_script =
-@LIBITM_BUILD_VERSIONED_SHLIB_TRUE@libitm_version_script = -Wl,--version-script,$(top_srcdir)/libitm.map
+@LIBITM_BUILD_VERSIONED_SHLIB_GNU_TRUE@@LIBITM_BUILD_VERSIONED_SHLIB_TRUE@libitm_version_script = -Wl,--version-script,$(top_srcdir)/libitm.map
+@LIBITM_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBITM_BUILD_VERSIONED_SHLIB_TRUE@libitm_version_script = -Wl,-M,libitm.map-sun
+@LIBITM_BUILD_VERSIONED_SHLIB_FALSE@libitm_version_dep =
+@LIBITM_BUILD_VERSIONED_SHLIB_GNU_TRUE@@LIBITM_BUILD_VERSIONED_SHLIB_TRUE@libitm_version_dep = $(top_srcdir)/libitm.map
+@LIBITM_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBITM_BUILD_VERSIONED_SHLIB_TRUE@libitm_version_dep = libitm.map-sun
libitm_version_info = -version-info $(libtool_VERSION)
# Force link with C, not C++. For now, while we're using C++ we don't
# want or need libstdc++.
-libitm_la_LINK = $(LINK)
-libitm_la_LDFLAGS = $(libitm_version_info) $(libitm_version_script) \
- -no-undefined
-
+libitm_la_DEPENDENCIES = $(libitm_version_dep)
+libitm_la_LINK = $(LINK) $(libitm_la_LDFLAGS)
+libitm_la_LDFLAGS = $(libitm_version_info) $(libitm_version_script)
libitm_la_SOURCES = aatree.cc alloc.cc alloc_c.cc alloc_cpp.cc \
barrier.cc beginend.cc clone.cc eh_cpp.cc local.cc query.cc \
retry.cc rwlock.cc useraction.cc util.cc sjlj.S tls.cc \
@@ -1258,6 +1263,15 @@ uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \
vpath % $(strip $(search_path))
+@LIBITM_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBITM_BUILD_VERSIONED_SHLIB_TRUE@libitm.map-sun : $(top_srcdir)/libitm.map \
+@LIBITM_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBITM_BUILD_VERSIONED_SHLIB_TRUE@ $(top_srcdir)/../contrib/make_sunver.pl \
+@LIBITM_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBITM_BUILD_VERSIONED_SHLIB_TRUE@ $(libitm_la_OBJECTS) $(libitm_la_LIBADD)
+@LIBITM_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBITM_BUILD_VERSIONED_SHLIB_TRUE@ perl $(top_srcdir)/../contrib/make_sunver.pl \
+@LIBITM_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBITM_BUILD_VERSIONED_SHLIB_TRUE@ $(top_srcdir)/libitm.map \
+@LIBITM_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBITM_BUILD_VERSIONED_SHLIB_TRUE@ $(libitm_la_OBJECTS:%.lo=.libs/%.o) \
+@LIBITM_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBITM_BUILD_VERSIONED_SHLIB_TRUE@ `echo $(libitm_la_LIBADD) | \
+@LIBITM_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBITM_BUILD_VERSIONED_SHLIB_TRUE@ sed 's,/\([^/.]*\)\.la,/.libs/\1.a,g'` \
+@LIBITM_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBITM_BUILD_VERSIONED_SHLIB_TRUE@ > $@ || (rm -f $@ ; exit 1)
@ARCH_X86_TRUE@x86_sse.lo : XCFLAGS += -msse
@ARCH_X86_AVX_TRUE@x86_avx.lo : XCFLAGS += -mavx
diff --git a/libitm/acinclude.m4 b/libitm/acinclude.m4
index 58fbf424c60..069738d8e80 100644
--- a/libitm/acinclude.m4
+++ b/libitm/acinclude.m4
@@ -98,7 +98,7 @@ AC_DEFUN([LIBITM_CHECK_SIZE_T_MANGLING], [
dnl Check if as supports AVX instructions.
AC_DEFUN([LIBITM_CHECK_AS_AVX], [
case "${target_cpu}" in
-i[3456]86 | x86_64)
+i[[34567]]86 | x86_64)
AC_CACHE_CHECK([if the assembler supports AVX], libitm_cv_as_avx, [
AC_TRY_COMPILE([], [asm("vzeroupper");],
[libitm_cv_as_avx=yes], [libitm_cv_as_avx=no])
@@ -169,6 +169,7 @@ dnl OPT_LDFLAGS='-Wl,-O1' if possible
dnl LD (as a side effect of testing)
dnl Sets:
dnl with_gnu_ld
+dnl libitm_ld_is_gold (possibly)
dnl libitm_gnu_ld_version (possibly)
dnl
dnl The last will be a single integer, e.g., version 1.23.45.0.67.89 will
@@ -200,9 +201,13 @@ AC_DEFUN([LIBITM_CHECK_LINKER_FEATURES], [
# Start by getting the version number. I think the libtool test already
# does some of this, but throws away the result.
+ libitm_ld_is_gold=no
+ if $LD --version 2>/dev/null | grep 'GNU gold'> /dev/null 2>&1; then
+ libitm_ld_is_gold=yes
+ fi
changequote(,)
- ldver=`$LD --version 2>/dev/null | head -1 | \
- sed -e 's/GNU ld \(version \)\{0,1\}\(([^)]*) \)\{0,1\}\([0-9.][0-9.]*\).*/\3/'`
+ ldver=`$LD --version 2>/dev/null |
+ sed -e 's/GNU gold /GNU ld /;s/GNU ld version /GNU ld /;s/GNU ld ([^)]*) /GNU ld /;s/GNU ld \([0-9.][0-9.]*\).*/\1/; q'`
changequote([,])
libitm_gnu_ld_version=`echo $ldver | \
$AWK -F. '{ if (NF<3) [$]3=0; print ([$]1*100+[$]2)*100+[$]3 }'`
@@ -272,16 +277,46 @@ AC_DEFUN([LIBITM_ENABLE_SYMVERS], [
LIBITM_ENABLE(symvers,yes,[=STYLE],
[enables symbol versioning of the shared library],
- [permit yes|no|gnu])
+ [permit yes|no|gnu*|sun])
# If we never went through the LIBITM_CHECK_LINKER_FEATURES macro, then we
# don't know enough about $LD to do tricks...
AC_REQUIRE([LIBITM_CHECK_LINKER_FEATURES])
-# FIXME The following test is too strict, in theory.
-if test $enable_shared = no ||
- test "x$LD" = x ||
- test x$libitm_gnu_ld_version = x; then
- enable_symvers=no
+
+# Turn a 'yes' into a suitable default.
+if test x$enable_symvers = xyes ; then
+ # FIXME The following test is too strict, in theory.
+ if test $enable_shared = no || test "x$LD" = x; then
+ enable_symvers=no
+ else
+ if test $with_gnu_ld = yes ; then
+ enable_symvers=gnu
+ else
+ case ${target_os} in
+ # Sun symbol versioning exists since Solaris 2.5.
+ solaris2.[[5-9]]* | solaris2.1[[0-9]]*)
+ enable_symvers=sun ;;
+ *)
+ enable_symvers=no ;;
+ esac
+ fi
+ fi
+fi
+
+# Check if 'sun' was requested on non-Solaris 2 platforms.
+if test x$enable_symvers = xsun ; then
+ case ${target_os} in
+ solaris2*)
+ # All fine.
+ ;;
+ *)
+ # Unlikely to work.
+ AC_MSG_WARN([=== You have requested Sun symbol versioning, but])
+ AC_MSG_WARN([=== you are not targetting Solaris 2.])
+ AC_MSG_WARN([=== Symbol versioning will be disabled.])
+ enable_symvers=no
+ ;;
+ esac
fi
# Check to see if libgcc_s exists, indicating that shared libgcc is possible.
@@ -318,12 +353,12 @@ libitm_min_gnu_ld_version=21400
# Check to see if unspecified "yes" value can win, given results above.
# Change "yes" into either "no" or a style name.
-if test $enable_symvers = yes; then
- if test $with_gnu_ld = yes &&
- test $libitm_shared_libgcc = yes;
- then
+if test $enable_symvers != no && test $libitm_shared_libgcc = yes; then
+ if test $with_gnu_ld = yes; then
if test $libitm_gnu_ld_version -ge $libitm_min_gnu_ld_version ; then
enable_symvers=gnu
+ elif test $libitm_ld_is_gold = yes ; then
+ enable_symvers=gnu
else
# The right tools, the right setup, but too old. Fallbacks?
AC_MSG_WARN(=== Linker version $libitm_gnu_ld_version is too old for)
@@ -342,6 +377,8 @@ if test $enable_symvers = yes; then
enable_symvers=no
fi
fi
+ elif test $enable_symvers = sun; then
+ : All interesting versions of Sun ld support sun style symbol versioning.
else
# just fail for now
AC_MSG_WARN([=== You have requested some kind of symbol versioning, but])
@@ -353,5 +390,7 @@ if test $enable_symvers = yes; then
fi
AM_CONDITIONAL(LIBITM_BUILD_VERSIONED_SHLIB, test $enable_symvers != no)
+AM_CONDITIONAL(LIBITM_BUILD_VERSIONED_SHLIB_GNU, test $enable_symvers = gnu)
+AM_CONDITIONAL(LIBITM_BUILD_VERSIONED_SHLIB_SUN, test $enable_symvers = sun)
AC_MSG_NOTICE(versioning on shared library symbols is $enable_symvers)
])
diff --git a/libitm/aclocal.m4 b/libitm/aclocal.m4
index 96617e6e4db..625404e06f6 100644
--- a/libitm/aclocal.m4
+++ b/libitm/aclocal.m4
@@ -1001,6 +1001,7 @@ m4_include([../config/multi.m4])
m4_include([../config/override.m4])
m4_include([../config/stdint.m4])
m4_include([../config/tls.m4])
+m4_include([../config/weakref.m4])
m4_include([../ltoptions.m4])
m4_include([../ltsugar.m4])
m4_include([../ltversion.m4])
diff --git a/libitm/alloc_cpp.cc b/libitm/alloc_cpp.cc
index 4e535513cd5..0789b2e5342 100644
--- a/libitm/alloc_cpp.cc
+++ b/libitm/alloc_cpp.cc
@@ -60,13 +60,17 @@ extern void _ZdlPvRKSt9nothrow_t (void *, c_nothrow_p) __attribute__((weak));
extern void *_ZnaXRKSt9nothrow_t (size_t, c_nothrow_p) __attribute__((weak));
extern void _ZdaPvRKSt9nothrow_t (void *, c_nothrow_p) __attribute__((weak));
-#ifdef __osf__ /* Really: !HAVE_WEAKDEF */
-void *
-_ZnaXRKSt9nothrow_t (size_t, c_nothrow_p)
-{
- return NULL;
-}
-#endif /* __osf__ */
+#if !defined (HAVE_ELF_STYLE_WEAKREF)
+void *_ZnwX (size_t) { return NULL; }
+void _ZdlPv (void *) { return; }
+void *_ZnaX (size_t) { return NULL; }
+void _ZdaPv (void *) { return; }
+
+void *_ZnwXRKSt9nothrow_t (size_t, c_nothrow_p) { return NULL; }
+void _ZdlPvRKSt9nothrow_t (void *, c_nothrow_p) { return; }
+void *_ZnaXRKSt9nothrow_t (size_t, c_nothrow_p) { return NULL; }
+void _ZdaPvRKSt9nothrow_t (void *, c_nothrow_p) { return; }
+#endif /* HAVE_ELF_STYLE_WEAKREF */
/* Wrap the delete nothrow symbols for usage with a single argument.
Perhaps should have a configure type check for this, because the
diff --git a/libitm/config.h.in b/libitm/config.h.in
index 52db1a6fdc1..1c3469cd5f9 100644
--- a/libitm/config.h.in
+++ b/libitm/config.h.in
@@ -30,6 +30,9 @@
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
+/* Define to 1 if target has a weakref that works like the ELF one. */
+#undef HAVE_ELF_STYLE_WEAKREF
+
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
diff --git a/libitm/config/generic/asmcfi.h b/libitm/config/generic/asmcfi.h
index fcb45c58739..4344d6f8f97 100644
--- a/libitm/config/generic/asmcfi.h
+++ b/libitm/config/generic/asmcfi.h
@@ -41,4 +41,4 @@
#define cfi_def_cfa(r,n)
#define cfi_register(o,n)
-#endif /* HAVE_ASM_CFI */
+#endif /* HAVE_AS_CFI_PSEUDO_OP */
diff --git a/libitm/config/x86/sjlj.S b/libitm/config/x86/sjlj.S
index 32572d9db60..39e0c758d6d 100644
--- a/libitm/config/x86/sjlj.S
+++ b/libitm/config/x86/sjlj.S
@@ -25,12 +25,39 @@
#include "asmcfi.h"
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+#ifdef __USER_LABEL_PREFIX__
+# define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+#else
+# define SYM(x) x
+#endif
+
+#ifdef __ELF__
+# define TYPE(x) .type SYM(x), @function
+# define SIZE(x) .size SYM(x), . - SYM(x)
+# ifdef HAVE_ATTRIBUTE_VISIBILITY
+# define HIDDEN(x) .hidden SYM(x)
+# else
+# define HIDDEN(x)
+# endif
+#else
+# define TYPE(x)
+# define SIZE(x)
+# ifdef __MACH__
+# define HIDDEN(x) .private_extern SYM(x)
+# else
+# define HIDDEN(x)
+# endif
+#endif
+
.text
.align 4
- .globl _ITM_beginTransaction
+ .globl SYM(_ITM_beginTransaction)
-_ITM_beginTransaction:
+SYM(_ITM_beginTransaction):
cfi_startproc
#ifdef __x86_64__
leaq 8(%rsp), %rax
@@ -46,7 +73,7 @@ _ITM_beginTransaction:
movq %r14, 48(%rsp)
movq %r15, 56(%rsp)
movq %rsp, %rsi
- call GTM_begin_transaction
+ call SYM(GTM_begin_transaction)
addq $72, %rsp
cfi_def_cfa_offset(8)
ret
@@ -60,22 +87,30 @@ _ITM_beginTransaction:
movl %edi, 20(%esp)
movl %ebp, 24(%esp)
leal 8(%esp), %edx
- call GTM_begin_transaction
+#if defined HAVE_ATTRIBUTE_VISIBILITY || !defined __PIC__
+ call SYM(GTM_begin_transaction)
+#elif defined __ELF__
+ call 1f
+1: popl %ebx
+ addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+ call SYM(GTM_begin_transaction)@PLT
+ movl 12(%esp), %ebx
+#else
+# error "Unsupported PIC sequence"
+#endif
addl $28, %esp
cfi_def_cfa_offset(4)
ret
#endif
cfi_endproc
-#ifdef __ELF__
- .type _ITM_beginTransaction, @function
- .size _ITM_beginTransaction, .-_ITM_beginTransaction
-#endif
+ TYPE(_ITM_beginTransaction)
+ SIZE(_ITM_beginTransaction)
.align 4
- .globl GTM_longjmp
+ .globl SYM(GTM_longjmp)
-GTM_longjmp:
+SYM(GTM_longjmp):
cfi_startproc
#ifdef __x86_64__
movq (%rdi), %rcx
@@ -106,11 +141,9 @@ GTM_longjmp:
#endif
cfi_endproc
-#ifdef __ELF__
- .type GTM_longjmp, @function
- .hidden GTM_longjmp
- .size GTM_longjmp, .-GTM_longjmp
-#endif
+ TYPE(GTM_longjmp)
+ HIDDEN(GTM_longjmp)
+ SIZE(GTM_longjmp)
#ifdef __linux__
.section .note.GNU-stack, "", @progbits
diff --git a/libitm/configure b/libitm/configure
index c0317ccfc4d..9b063594111 100644
--- a/libitm/configure
+++ b/libitm/configure
@@ -611,6 +611,10 @@ link_itm
XLDFLAGS
XCFLAGS
config_path
+LIBITM_BUILD_VERSIONED_SHLIB_SUN_FALSE
+LIBITM_BUILD_VERSIONED_SHLIB_SUN_TRUE
+LIBITM_BUILD_VERSIONED_SHLIB_GNU_FALSE
+LIBITM_BUILD_VERSIONED_SHLIB_GNU_TRUE
LIBITM_BUILD_VERSIONED_SHLIB_FALSE
LIBITM_BUILD_VERSIONED_SHLIB_TRUE
OPT_LDFLAGS
@@ -9951,7 +9955,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct=yes
hardcode_minus_L=yes
@@ -10864,7 +10868,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -10882,7 +10886,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
@@ -11716,7 +11720,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11719 "configure"
+#line 11723 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11822,7 +11826,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11825 "configure"
+#line 11829 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -12748,7 +12752,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
esac
;;
- freebsd[12]*)
+ freebsd2.*)
# C++ shared libraries reported to be fairly broken before
# switch to ELF
ld_shlibs_CXX=no
@@ -14523,7 +14527,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -14541,7 +14545,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
@@ -16688,9 +16692,13 @@ with_gnu_ld=$lt_cv_prog_gnu_ld
# Start by getting the version number. I think the libtool test already
# does some of this, but throws away the result.
+ libitm_ld_is_gold=no
+ if $LD --version 2>/dev/null | grep 'GNU gold'> /dev/null 2>&1; then
+ libitm_ld_is_gold=yes
+ fi
- ldver=`$LD --version 2>/dev/null | head -1 | \
- sed -e 's/GNU ld \(version \)\{0,1\}\(([^)]*) \)\{0,1\}\([0-9.][0-9.]*\).*/\3/'`
+ ldver=`$LD --version 2>/dev/null |
+ sed -e 's/GNU gold /GNU ld /;s/GNU ld version /GNU ld /;s/GNU ld ([^)]*) /GNU ld /;s/GNU ld \([0-9.][0-9.]*\).*/\1/; q'`
libitm_gnu_ld_version=`echo $ldver | \
$AWK -F. '{ if (NF<3) $3=0; print ($1*100+$2)*100+$3 }'`
@@ -16764,7 +16772,7 @@ $as_echo "$ac_sectionLDflags" >&6; }
if test "${enable_symvers+set}" = set; then :
enableval=$enable_symvers;
case "$enableval" in
- yes|no|gnu) ;;
+ yes|no|gnu*|sun) ;;
*) as_fn_error "Unknown argument to enable/disable symvers" "$LINENO" 5 ;;
esac
@@ -16777,11 +16785,44 @@ fi
# If we never went through the LIBITM_CHECK_LINKER_FEATURES macro, then we
# don't know enough about $LD to do tricks...
-# FIXME The following test is too strict, in theory.
-if test $enable_shared = no ||
- test "x$LD" = x ||
- test x$libitm_gnu_ld_version = x; then
- enable_symvers=no
+
+# Turn a 'yes' into a suitable default.
+if test x$enable_symvers = xyes ; then
+ # FIXME The following test is too strict, in theory.
+ if test $enable_shared = no || test "x$LD" = x; then
+ enable_symvers=no
+ else
+ if test $with_gnu_ld = yes ; then
+ enable_symvers=gnu
+ else
+ case ${target_os} in
+ # Sun symbol versioning exists since Solaris 2.5.
+ solaris2.[5-9]* | solaris2.1[0-9]*)
+ enable_symvers=sun ;;
+ *)
+ enable_symvers=no ;;
+ esac
+ fi
+ fi
+fi
+
+# Check if 'sun' was requested on non-Solaris 2 platforms.
+if test x$enable_symvers = xsun ; then
+ case ${target_os} in
+ solaris2*)
+ # All fine.
+ ;;
+ *)
+ # Unlikely to work.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: === You have requested Sun symbol versioning, but" >&5
+$as_echo "$as_me: WARNING: === You have requested Sun symbol versioning, but" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: === you are not targetting Solaris 2." >&5
+$as_echo "$as_me: WARNING: === you are not targetting Solaris 2." >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: === Symbol versioning will be disabled." >&5
+$as_echo "$as_me: WARNING: === Symbol versioning will be disabled." >&2;}
+ enable_symvers=no
+ ;;
+ esac
fi
# Check to see if libgcc_s exists, indicating that shared libgcc is possible.
@@ -16850,12 +16891,12 @@ libitm_min_gnu_ld_version=21400
# Check to see if unspecified "yes" value can win, given results above.
# Change "yes" into either "no" or a style name.
-if test $enable_symvers = yes; then
- if test $with_gnu_ld = yes &&
- test $libitm_shared_libgcc = yes;
- then
+if test $enable_symvers != no && test $libitm_shared_libgcc = yes; then
+ if test $with_gnu_ld = yes; then
if test $libitm_gnu_ld_version -ge $libitm_min_gnu_ld_version ; then
enable_symvers=gnu
+ elif test $libitm_ld_is_gold = yes ; then
+ enable_symvers=gnu
else
# The right tools, the right setup, but too old. Fallbacks?
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: === Linker version $libitm_gnu_ld_version is too old for" >&5
@@ -16878,6 +16919,8 @@ $as_echo "$as_me: WARNING: === Symbol versioning will be disabled." >&2;}
enable_symvers=no
fi
fi
+ elif test $enable_symvers = sun; then
+ : All interesting versions of Sun ld support sun style symbol versioning.
else
# just fail for now
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: === You have requested some kind of symbol versioning, but" >&5
@@ -16900,6 +16943,22 @@ else
LIBITM_BUILD_VERSIONED_SHLIB_FALSE=
fi
+ if test $enable_symvers = gnu; then
+ LIBITM_BUILD_VERSIONED_SHLIB_GNU_TRUE=
+ LIBITM_BUILD_VERSIONED_SHLIB_GNU_FALSE='#'
+else
+ LIBITM_BUILD_VERSIONED_SHLIB_GNU_TRUE='#'
+ LIBITM_BUILD_VERSIONED_SHLIB_GNU_FALSE=
+fi
+
+ if test $enable_symvers = sun; then
+ LIBITM_BUILD_VERSIONED_SHLIB_SUN_TRUE=
+ LIBITM_BUILD_VERSIONED_SHLIB_SUN_FALSE='#'
+else
+ LIBITM_BUILD_VERSIONED_SHLIB_SUN_TRUE='#'
+ LIBITM_BUILD_VERSIONED_SHLIB_SUN_FALSE=
+fi
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: versioning on shared library symbols is $enable_symvers" >&5
$as_echo "$as_me: versioning on shared library symbols is $enable_symvers" >&6;}
@@ -17118,7 +17177,7 @@ $as_echo "#define HAVE_64BIT_SYNC_BUILTINS 1" >>confdefs.h
fi
case "${target_cpu}" in
-i345686 | x86_64)
+i[34567]86 | x86_64)
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the assembler supports AVX" >&5
$as_echo_n "checking if the assembler supports AVX... " >&6; }
if test "${libitm_cv_as_avx+set}" = set; then :
@@ -17154,6 +17213,57 @@ $as_echo "#define HAVE_AS_AVX 1" >>confdefs.h
;;
esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether weak refs work like ELF" >&5
+$as_echo_n "checking whether weak refs work like ELF... " >&6; }
+if test "${ac_cv_have_elf_style_weakref+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ weakref_m4_saved_CFLAGS="$CFLAGS"
+ case "${host}" in
+ *-apple-darwin*) CFLAGS="$CFLAGS -Wl,-undefined,dynamic_lookup" ;;
+ *) ;;
+ esac
+ if test "$cross_compiling" = yes; then :
+
+case "${host}" in
+ alpha*-dec-osf*) ac_cv_have_elf_style_weakref=no ;;
+ *-apple-darwin[89]*) ac_cv_have_elf_style_weakref=no ;;
+ *) ac_cv_have_elf_style_weakref=yes;;
+esac
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+extern void fNotToBeFound(void) __attribute__((weak));
+int main ()
+{
+ if (fNotToBeFound)
+ return 1;
+ else
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_have_elf_style_weakref=yes
+else
+ ac_cv_have_elf_style_weakref=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+CFLAGS="$weakref_m4_saved_CFLAGS"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_elf_style_weakref" >&5
+$as_echo "$ac_cv_have_elf_style_weakref" >&6; }
+if test x"$ac_cv_have_elf_style_weakref" = xyes; then
+
+$as_echo "#define HAVE_ELF_STYLE_WEAKREF 1" >>confdefs.h
+
+fi
+
# Cleanup and exit.
CFLAGS="$save_CFLAGS"
cat >confcache <<\_ACEOF
@@ -17424,6 +17534,14 @@ if test -z "${LIBITM_BUILD_VERSIONED_SHLIB_TRUE}" && test -z "${LIBITM_BUILD_VER
as_fn_error "conditional \"LIBITM_BUILD_VERSIONED_SHLIB\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${LIBITM_BUILD_VERSIONED_SHLIB_GNU_TRUE}" && test -z "${LIBITM_BUILD_VERSIONED_SHLIB_GNU_FALSE}"; then
+ as_fn_error "conditional \"LIBITM_BUILD_VERSIONED_SHLIB_GNU\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LIBITM_BUILD_VERSIONED_SHLIB_SUN_TRUE}" && test -z "${LIBITM_BUILD_VERSIONED_SHLIB_SUN_FALSE}"; then
+ as_fn_error "conditional \"LIBITM_BUILD_VERSIONED_SHLIB_SUN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -z "${ARCH_X86_TRUE}" && test -z "${ARCH_X86_FALSE}"; then
as_fn_error "conditional \"ARCH_X86\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
diff --git a/libitm/configure.ac b/libitm/configure.ac
index 672b71279e3..45ee8701e38 100644
--- a/libitm/configure.ac
+++ b/libitm/configure.ac
@@ -239,6 +239,8 @@ LIBITM_CHECK_SYNC_BUILTINS
LIBITM_CHECK_64BIT_SYNC_BUILTINS
LIBITM_CHECK_AS_AVX
+GCC_CHECK_ELF_STYLE_WEAKREF
+
# Cleanup and exit.
CFLAGS="$save_CFLAGS"
AC_CACHE_SAVE
diff --git a/libitm/eh_cpp.cc b/libitm/eh_cpp.cc
index 7cba97cc48c..6f302cdc4ae 100644
--- a/libitm/eh_cpp.cc
+++ b/libitm/eh_cpp.cc
@@ -39,6 +39,14 @@ extern void *__cxa_begin_catch (void *) WEAK;
extern void *__cxa_end_catch (void) WEAK;
extern void __cxa_tm_cleanup (void *, void *, unsigned int) WEAK;
+#if !defined (HAVE_ELF_STYLE_WEAKREF)
+void *__cxa_allocate_exception (size_t) { return NULL; }
+void __cxa_throw (void *, void *, void *) { return; }
+void *__cxa_begin_catch (void *) { return NULL; }
+void *__cxa_end_catch (void) { return NULL; }
+void __cxa_tm_cleanup (void *, void *, unsigned int) { return; }
+#endif /* HAVE_ELF_STYLE_WEAKREF */
+
}
diff --git a/libitm/libitm_i.h b/libitm/libitm_i.h
index 58e43b01281..ba1afb4710c 100644
--- a/libitm/libitm_i.h
+++ b/libitm/libitm_i.h
@@ -240,9 +240,15 @@ struct gtm_thread
// Invoked from assembly language, thus the "asm" specifier on
// the name, avoiding complex name mangling.
+#ifdef __USER_LABEL_PREFIX__
+#define UPFX1(t) UPFX(t)
+#define UPFX(t) #t
+ static uint32_t begin_transaction(uint32_t, const gtm_jmpbuf *)
+ __asm__(UPFX1(__USER_LABEL_PREFIX__) "GTM_begin_transaction") ITM_REGPARM;
+#else
static uint32_t begin_transaction(uint32_t, const gtm_jmpbuf *)
__asm__("GTM_begin_transaction") ITM_REGPARM;
-
+#endif
// In eh_cpp.cc
void revert_cpp_exceptions (gtm_transaction_cp *cp = 0);
diff --git a/libitm/testsuite/Makefile.in b/libitm/testsuite/Makefile.in
index 6990cfeb681..8066a2a0388 100644
--- a/libitm/testsuite/Makefile.in
+++ b/libitm/testsuite/Makefile.in
@@ -47,10 +47,12 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
$(top_srcdir)/../config/multi.m4 \
$(top_srcdir)/../config/override.m4 \
$(top_srcdir)/../config/stdint.m4 \
- $(top_srcdir)/../config/tls.m4 $(top_srcdir)/../ltoptions.m4 \
- $(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \
- $(top_srcdir)/../lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
- $(top_srcdir)/../libtool.m4 $(top_srcdir)/configure.ac
+ $(top_srcdir)/../config/tls.m4 \
+ $(top_srcdir)/../config/weakref.m4 \
+ $(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
+ $(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/../libtool.m4 \
+ $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
diff --git a/libitm/testsuite/lib/libitm.exp b/libitm/testsuite/lib/libitm.exp
index 701120aa557..74f7f80859a 100644
--- a/libitm/testsuite/lib/libitm.exp
+++ b/libitm/testsuite/lib/libitm.exp
@@ -144,7 +144,7 @@ proc libitm_init { args } {
# We use atomic operations in the testcases to validate results.
if { ([istarget i?86-*-*] || [istarget x86_64-*-*])
- && [check_effective_target_ilp32] } {
+ && [check_effective_target_ia32] } {
lappend ALWAYS_CFLAGS "additional_flags=-march=i486"
}
diff --git a/libitm/testsuite/libitm.c/memcpy-1.c b/libitm/testsuite/libitm.c/memcpy-1.c
index e4b56573b26..03b381285df 100644
--- a/libitm/testsuite/libitm.c/memcpy-1.c
+++ b/libitm/testsuite/libitm.c/memcpy-1.c
@@ -84,6 +84,12 @@ do_test (size_t align1, size_t align2, size_t len)
}
}
+#ifndef MAP_ANONYMOUS
+# ifdef MAP_ANON
+# define MAP_ANONYMOUS MAP_ANON
+# endif
+#endif
+
int main()
{
size_t i, j;
diff --git a/libitm/testsuite/libitm.c/memset-1.c b/libitm/testsuite/libitm.c/memset-1.c
index 87bf6c62322..11aea458ca1 100644
--- a/libitm/testsuite/libitm.c/memset-1.c
+++ b/libitm/testsuite/libitm.c/memset-1.c
@@ -33,6 +33,12 @@ static unsigned char *buf;
static size_t bufsize, page_size;
static int fail;
+#ifndef MAP_ANONYMOUS
+# ifdef MAP_ANON
+# define MAP_ANONYMOUS MAP_ANON
+# endif
+#endif
+
static void
do_test (size_t align, size_t len)
{
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 7ff941e459f..e856e4b65d7 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,16 @@
+2011-11-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR bootstrap/50888
+ * prims.cc: Don't include ctype.h.
+ (c_isspace): Define.
+ (next_property_key, next_property_value): Use it instead
+ of isspace.
+
+2011-11-21 Andreas Tobler <andreast@fgznet.ch>
+
+ * configure.ac: Fix FreeBSD 10 detection.
+ * configure: Regenerate.
+
2011-10-17 Paul Brook <paul@codesourcery.com>
* exception.cc (parse_lsda_header): hardcode ttype_encoding for older
diff --git a/libjava/configure b/libjava/configure
index b38728e1957..e6c5b0cf66c 100755
--- a/libjava/configure
+++ b/libjava/configure
@@ -11573,7 +11573,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct=yes
hardcode_minus_L=yes
@@ -12489,7 +12489,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -12507,7 +12507,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
@@ -14397,7 +14397,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
esac
;;
- freebsd[12]*)
+ freebsd2.*)
# C++ shared libraries reported to be fairly broken before
# switch to ELF
ld_shlibs_CXX=no
@@ -16172,7 +16172,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -16190,7 +16190,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
@@ -18533,7 +18533,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct_GCJ=yes
hardcode_minus_L_GCJ=yes
@@ -20731,7 +20731,7 @@ case "$THREADS" in
*-*-cygwin*)
# Don't set THREADLIBS here. Cygwin doesn't have -lpthread.
;;
- *-*-freebsd[1234]*)
+ *-*-freebsd[34].*)
# Before FreeBSD 5, it didn't have -lpthread (or any library which
# merely adds pthread_* functions) but it does have a -pthread switch
# which is required at link-time to select -lc_r *instead* of -lc.
diff --git a/libjava/configure.ac b/libjava/configure.ac
index f0ed99ca248..d308c4f1a6b 100644
--- a/libjava/configure.ac
+++ b/libjava/configure.ac
@@ -1075,7 +1075,7 @@ case "$THREADS" in
*-*-cygwin*)
# Don't set THREADLIBS here. Cygwin doesn't have -lpthread.
;;
- *-*-freebsd[[1234]]*)
+ *-*-freebsd[[34]].*)
# Before FreeBSD 5, it didn't have -lpthread (or any library which
# merely adds pthread_* functions) but it does have a -pthread switch
# which is required at link-time to select -lc_r *instead* of -lc.
diff --git a/libjava/libltdl/ChangeLog b/libjava/libltdl/ChangeLog
index 708cb383578..df5ce43462d 100644
--- a/libjava/libltdl/ChangeLog
+++ b/libjava/libltdl/ChangeLog
@@ -1,3 +1,8 @@
+2011-11-21 Andreas Tobler <andreast@fgznet.ch>
+
+ * acinclude.m4: Additional FreeBSD 10 fixes.
+ * configure: Regenerate.
+
2011-02-13 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
* acinclude.m4 (AC_LIBTOOL_PROG_LD_SHLIBS)
diff --git a/libjava/libltdl/acinclude.m4 b/libjava/libltdl/acinclude.m4
index 55beab162e7..d77a1a3990d 100644
--- a/libjava/libltdl/acinclude.m4
+++ b/libjava/libltdl/acinclude.m4
@@ -1377,7 +1377,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[[01]]* | freebsdelf3.[[01]]*)
@@ -3035,7 +3035,7 @@ case $host_os in
;;
esac
;;
- freebsd[[12]]*)
+ freebsd2.*)
# C++ shared libraries reported to be fairly broken before switch to ELF
_LT_AC_TAGVAR(ld_shlibs, $1)=no
;;
@@ -5669,7 +5669,7 @@ EOF
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
_LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
_LT_AC_TAGVAR(hardcode_direct, $1)=yes
_LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
diff --git a/libjava/libltdl/configure b/libjava/libltdl/configure
index f47d95f7369..35b89dc5551 100755
--- a/libjava/libltdl/configure
+++ b/libjava/libltdl/configure
@@ -7355,7 +7355,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct=yes
hardcode_minus_L=yes
@@ -7968,7 +7968,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
diff --git a/libjava/prims.cc b/libjava/prims.cc
index 666f49d26bd..652cf5b4aa5 100644
--- a/libjava/prims.cc
+++ b/libjava/prims.cc
@@ -38,8 +38,6 @@ details. */
#endif
#ifndef DISABLE_GETENV_PROPERTIES
-#define __NO_CTYPE 1
-#include <ctype.h>
#include <java-props.h>
#define PROCESS_GCJ_PROPERTIES process_gcj_properties()
#else
@@ -986,6 +984,8 @@ static java::lang::Thread *main_thread;
#ifndef DISABLE_GETENV_PROPERTIES
+#define c_isspace(c) (memchr (" \t\n\r\v\f", c, 6) != NULL)
+
static char *
next_property_key (char *s, size_t *length)
{
@@ -994,7 +994,7 @@ next_property_key (char *s, size_t *length)
JvAssert (s);
// Skip over whitespace
- while (isspace (*s))
+ while (c_isspace (*s))
s++;
// If we've reached the end, return NULL. Also return NULL if for
@@ -1006,7 +1006,7 @@ next_property_key (char *s, size_t *length)
// Determine the length of the property key.
while (s[l] != 0
- && ! isspace (s[l])
+ && ! c_isspace (s[l])
&& s[l] != ':'
&& s[l] != '=')
{
@@ -1028,19 +1028,19 @@ next_property_value (char *s, size_t *length)
JvAssert (s);
- while (isspace (*s))
+ while (c_isspace (*s))
s++;
if (*s == ':'
|| *s == '=')
s++;
- while (isspace (*s))
+ while (c_isspace (*s))
s++;
// Determine the length of the property value.
while (s[l] != 0
- && ! isspace (s[l])
+ && ! c_isspace (s[l])
&& s[l] != ':'
&& s[l] != '=')
{
diff --git a/libmudflap/ChangeLog b/libmudflap/ChangeLog
index e4754d5701b..355286092e5 100644
--- a/libmudflap/ChangeLog
+++ b/libmudflap/ChangeLog
@@ -1,3 +1,7 @@
+2011-11-21 Andreas Tobler <andreast@fgznet.ch>
+
+ * configure: Regenerate.
+
2011-07-31 Tom de Vries <tom@codesourcery.com>
PR middle-end/43513
diff --git a/libmudflap/configure b/libmudflap/configure
index 3ce3979bda2..f1c74a1f5ee 100755
--- a/libmudflap/configure
+++ b/libmudflap/configure
@@ -8842,7 +8842,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct=yes
hardcode_minus_L=yes
@@ -9755,7 +9755,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -9773,7 +9773,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog
index 474849480e0..3999b439b9d 100644
--- a/libobjc/ChangeLog
+++ b/libobjc/ChangeLog
@@ -1,3 +1,7 @@
+2011-11-21 Andreas Tobler <andreast@fgznet.ch>
+
+ * configure: Regenerate.
+
2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* Makefile.in (INCLUDES): Add -I$(MULTIBUILDTOP)../libgcc.
diff --git a/libobjc/configure b/libobjc/configure
index 59e3d98a7a5..8c07356af0c 100755
--- a/libobjc/configure
+++ b/libobjc/configure
@@ -8808,7 +8808,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct=yes
hardcode_minus_L=yes
@@ -9724,7 +9724,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -9742,7 +9742,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
diff --git a/libquadmath/ChangeLog b/libquadmath/ChangeLog
index 73c2c420f00..96c61861f24 100644
--- a/libquadmath/ChangeLog
+++ b/libquadmath/ChangeLog
@@ -1,3 +1,7 @@
+2011-11-21 Andreas Tobler <andreast@fgznet.ch>
+
+ * configure: Regenerate.
+
2011-11-07 Kai Tietz <ktietz@redhat.com>
PR target/51007
diff --git a/libquadmath/configure b/libquadmath/configure
index 7f78ea15868..9d979337d18 100755
--- a/libquadmath/configure
+++ b/libquadmath/configure
@@ -8727,7 +8727,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct=yes
hardcode_minus_L=yes
@@ -9643,7 +9643,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -9661,7 +9661,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
diff --git a/libssp/ChangeLog b/libssp/ChangeLog
index d8f42a94dab..308f6fa7c0a 100644
--- a/libssp/ChangeLog
+++ b/libssp/ChangeLog
@@ -1,3 +1,7 @@
+2011-11-21 Andreas Tobler <andreast@fgznet.ch>
+
+ * configure: Regenerate.
+
2011-03-21 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
PR bootstrap/48135
diff --git a/libssp/configure b/libssp/configure
index b1edcb4295b..bd3f5662c4b 100755
--- a/libssp/configure
+++ b/libssp/configure
@@ -8864,7 +8864,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct=yes
hardcode_minus_L=yes
@@ -9780,7 +9780,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -9798,7 +9798,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 5eb3f8d4376..1d4dff8747c 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,254 @@
+2011-11-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/51288
+ * include/std/iomanip (get_money, put_money): Use sentry.
+ * testsuite/27_io/manipulators/extended/get_money/char/51288.cc: New.
+ * testsuite/27_io/manipulators/extended/get_money/wchar_t/51288.cc:
+ Likewise.
+ * testsuite/27_io/manipulators/extended/put_money/char/51288.cc:
+ Likewise.
+ * testsuite/27_io/manipulators/extended/put_money/wchar_t/51288.cc:
+ Likewise.
+
+2011-11-27 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * doc/xml/manual/using.xml (Prerequisites): Refer to x86 instead
+ of i386.
+
+2011-11-27 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * scripts/run_doxygen (problematic): Change Linux reference to
+ GNU/Linux.
+
+2011-11-26 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * doc/xml/manual/abi.xml (Prerequisites): Refer to GNU/Linux.
+ Fix reference to GCC.
+
+2011-11-26 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ PR libstdc++/51296
+ * testsuite/30_threads/thread/native_handle/typesizes.cc: Do not run
+ on alpha*-*-osf*.
+ * testsuite/30_threads/future/cons/constexpr.cc: Disable debug
+ symbols.
+ * testsuite/30_threads/shared_future/cons/constexpr.cc: Likewise.
+
+2011-11-23 François Dumont <fdumont@gcc.gnu.org>
+
+ PR libstdc++/41975
+ * include/bits/hashtable.h (_Hashtable<>): Major data model
+ modification to limit performance impact of empty buckets in
+ erase(iterator) implementation.
+ * include/bits/hashtable_policy.h (_Hashtable_iterator,
+ _Hashtable_const_iterator): Remove not used anymore.
+ * include/bits/hashtable_policy.h (_Prime_rehash_policy): Remove
+ _M_grow_factor, just use natural evolution of prime numbers. Add
+ _M_prev_size to know when the number of buckets can be reduced.
+ * include/bits/unordered_set.h (__unordered_set<>,
+ __unordered_multiset<>), unordered_map.h (__unordered_map<>,
+ __unordered_multimap<>): Change default value of cache hash code
+ template parameter, false for integral types with noexcept hash
+ functor, true otherwise.
+ * include/debug/unordered_map, unordered_set: Adapt transformation
+ from iterator/const_iterator to respectively
+ local_iterator/const_local_iterator.
+ * testsuite/performance/23_containers/copy_construct/unordered_set.cc:
+ New.
+ * testsuite/23_containers/unordered_set/instantiation_neg.cc: New.
+ * testsuite/23_containers/unordered_set/hash_policy/rehash.cc: New.
+ * testsuite/23_containers/unordered_multiset/cons/copy.cc: New.
+ * testsuite/23_containers/unordered_multiset/erase/1.cc,
+ 24061-multiset.cc: Add checks on the number of bucket elements.
+ * testsuite/23_containers/unordered_multiset/insert/multiset_range.cc,
+ multiset_single.cc, multiset_single_move.cc: Likewise.
+
+2011-11-21 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * include/std/functional (is_placeholder, is_bind_expression): Add
+ partial specializations for cv-qualified types.
+ * include/tr1/functional (is_placeholder, is_bind_expression): Add
+ partial specializations for std::bind and std::placeholders and for
+ cv-qualified types.
+ * testsuite/20_util/bind/cv_quals_3.cc: New.
+ * testsuite/tr1/3_function_objects/bind/cv_quals.cc: New.
+ * testsuite/tr1/3_function_objects/bind/mixed.cc: New.
+
+2011-11-21 Andreas Tobler <andreast@fgznet.ch>
+
+ * configure: Regenerate.
+
+2011-11-21 Daniel Krugler <daniel.kruegler@googlemail.com>
+
+ PR libstdc++/51185
+ * include/std/type_traits (__is_base_to_derived_ref,
+ __is_lvalue_to_rvalue_ref): Fix.
+ * testsuite/20_util/is_constructible/51185.cc: New.
+ * testsuite/20_util/is_constructible/value-2.cc: Extend.
+ * testsuite/20_util/declval/requirements/1_neg.cc: Adjust dg-error
+ line number.
+ * testsuite/20_util/make_signed/requirements/typedefs_neg.cc:
+ Likewise.
+ * testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
+ Likewise.
+
+2011-11-21 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * include/std/tuple (__conv_types, __one_by_one_convertible,
+ __all_convertible): Remove.
+ (tuple<>::tuple(_UElements&&...),
+ tuple<>::tuple(const tuple<_UElements...>&),
+ tuple<>::tuple(tuple<_UElements...>&&)): Remove wa for c++/48322.
+ * testsuite/20_util/uses_allocator/cons_neg.cc: Adjust dg-error
+ line number.
+
+2011-11-20 Jason Merrill <jason@redhat.com>
+
+ PR c++/48322
+ * include/std/tuple (tuple(_UElements&&...)): Fix SFINAE.
+
+ * testsuite/20_util/bind/ref_neg.cc: Adjust error markings.
+
+2011-11-20 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * include/backward/binders.h: Fix examples in doxygen comments and
+ suggest using std::bind instead.
+
+2011-11-20 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * doc/xml/manual/status_cxx2011.xml: Fix docbook markup.
+
+2011-11-20 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * doc/xml/manual/appendix_contributing.xml: Do not use "here" as link
+ text.
+ * doc/xml/faq.xml: Likewise. Do not request standard library issues
+ to be reported to the libstdc++ mailing list.
+ * doc/xml/manual/status_cxx2011.xml: Document implementation-defined
+ behaviour.
+ * doc/xml/manual/status_cxxtr1.xml: Likewise.
+ * doc/xml/manual/utilities.xml: Fix grammar, probably caused by a
+ global search and replace of "part" by "chapter".
+ * doc/xml/manual/shared_ptr.xml: Remove outdated information.
+ * doc/xml/manual/messages.xml: Be more specific about systems where
+ using 'int' for catalog handle is not a problem, mention LWG issue.
+
+2011-11-19 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * include/debug/bitset (operator[](size_t) const): Declare constexpr.
+ * include/profile/bitset: Likewise.
+ * testsuite/23_containers/bitset/operations/constexpr.cc: Split out
+ non portable bits to...
+ * testsuite/23_containers/bitset/operations/constexpr-2.cc: ... here.
+
+2011-11-18 Harti Brandt <hartmut.brandt@dlr.de>
+
+ PR libstdc++/51209
+ * include/bits/hashtable.h (_Hashtable<>::_M_find_node): Return
+ nullptr when no node is found.
+ * include/tr1/hashtable.h (_Hashtable<>::_M_find_node): Return
+ zero when no node is found.
+
+2011-11-18 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * src/hash-long-double-aux.cc: Rename to...
+ * src/hash-long-double-tr1-aux.cc: ... this.
+ * src/compatibility-ldbl.cc: Adjust.
+ * src/hash_tr1.cc: Likewise.
+ * src/hash_c++0x.cc: Don't use src/hash-long-double-aux.cc.
+ * include/bits/functional_hash.h (hash<_Tp*>::operator(), specs
+ for integer types, hash<float>::operator(), hash<double>::operator(),
+ hash<long double>::operator()): Declare noexcept.
+ * include/debug/bitset (hash<__debug::bitset>::operator()): Likewise.
+ * include/debug/vector (hash<__debug::vector>::operator()): Likewise.
+ * include/std/system_error (hash<error_code>::operator()): Likewise.
+ * include/std/thread (hash<thread::id>::operator()): Likewise.
+ * include/std/bitset (hash<bitset>::operator()): Likewise.
+ * include/std/typeindex (hash<type_index>::operator()): Likewise.
+ * include/profile/bitset (hash<__profile::vector>::operator()):
+ Likewise.
+ * include/profile/vector (hash<__profile::vector>::operator()):
+ Likewise.
+ * include/ext/vstring.h (hash<__vstring>::operator(),
+ hash<__wvstring>::operator(), hash<__u16vstring>::operator(),
+ hash<__u32vstring>::operator()): Likewise.
+ * include/bits/shared_ptr.h (hash<shared_ptr>::operator()): Likewise.
+ * include/bits/shared_ptr_base.h (hash<__shared_ptr>::operator()):
+ Likewise.
+ * include/bits/unique_ptr.h (hash<unique_ptr>::operator()): Likewise.
+ * include/bits/basic_string.h (hash<string>::operator(),
+ hash<wstring>::operator(), hash<u16string>::operator(),
+ hash<u32string>::operator()): Likewise.
+ * include/bits/vector.tcc (hash<vector>::operator()): Likewise.
+ * include/bits/stl_bvector.h (hash<vector>::operator()): Likewise.
+ * libsupc++/typeinfo (type_info::hash_code): Use noexcept instead of
+ throw().
+
+2011-11-17 Richard Henderson <rth@redhat.com>
+
+ PR libstdc++/51181
+ * libsupc++/eh_tm.cc (free_any_cxa_exception): Protect the use
+ of __sync_sub_and_fetch with _GLIBCXX_ATOMIC_BUILTINS_4.
+
+2011-11-18 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * testsuite/30_threads/thread/native_handle/typesizes.cc: Do not run
+ on darwin.
+
+2011-11-17 Jason Merrill <jason@redhat.com>
+
+ * testsuite/21_strings/basic_string/cons/char/moveable2.cc
+ (tstring): Add defaulted move assignment.
+ * testsuite/21_strings/basic_string/cons/wchar_t/moveable2.cc
+ (tstring): Add defaulted move assignment.
+ * testsuite/util/testsuite_tr1.h (NoexceptMoveConsClass): Add
+ defaulted move assignment operator.
+ (NoexceptMoveAssignClass): Add defaulted move constructor.
+
+2011-11-17 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * doc/xml/manual/status_cxx2011.xml: Status of piecewise construction
+ and ios_base::failure.
+ * doc/xml/manual/backwards_compatibility.xml: List headers in
+ alphabetical order.
+
+2011-11-16 Andrew MacLeod <amacleod@redhat.com>
+
+ PR libstdc++/51102
+ * include/bits/atomic_base.h (ATOMIC_BOOL_LOCK_FREE,
+ ATOMIC_POINTER_LOCK_FREE): New. Add missing macros.
+
+2011-11-15 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/51142
+ * include/debug/unordered_map (unordered_map<>::erase(iterator),
+ unordered_multimap<>::erase(iterator)): Add, consistently with
+ LWG 2059.
+ * include/debug/unordered_set (unordered_set<>::erase(iterator),
+ unordered_multiset<>::erase(iterator)): Likewise.
+ * include/debug/map.h (map<>::erase(iterator)): Likewise.
+ * include/debug/multimap.h (multimap<>::erase(iterator)): Likewise.
+ * include/profile/map.h (map<>::erase(iterator)): Likewise.
+ * include/profile/multimap.h (multimap<>::erase(iterator)): Likewise.
+ * include/bits/hashtable.h (_Hashtable<>::erase(iterator)): Likewise.
+ * include/bits/stl_map.h (map<>::erase(iterator)): Likewise.
+ * include/bits/stl_multimap.h (multimap<>::erase(iterator)): Likewise.
+ * include/bits/stl_tree.h (_Rb_tree<>::erase(iterator)): Likewise.
+ * testsuite/23_containers/unordered_map/erase/51142.cc: New.
+ * testsuite/23_containers/multimap/modifiers/erase/51142.cc: Likewise.
+ * testsuite/23_containers/set/modifiers/erase/51142.cc: Likewise.
+ * testsuite/23_containers/unordered_multimap/erase/51142.cc: Likewise.
+ * testsuite/23_containers/unordered_set/erase/51142.cc: Likewise.
+ * testsuite/23_containers/multiset/modifiers/erase/51142.cc: Likewise.
+ * testsuite/23_containers/unordered_multiset/erase/51142.cc: Likewise.
+ * testsuite/23_containers/map/modifiers/erase/51142.cc: Likewise.
+
+2011-11-15 Jason Dick <dickphd@gmail.com>
+
+ PR libstdc++/51133
+ * include/tr1/poly_hermite.tcc (__poly_hermite_recursion): Fix
+ wrong sign in recursion relation.
+
2011-11-14 Paolo Carlini <paolo.carlini@oracle.com>
* include/c_global/cmath (frexp, modf, remquo): Do not mark constexpr,
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index fa755b47236..52218367919 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -9702,7 +9702,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct=yes
hardcode_minus_L=yes
@@ -10618,7 +10618,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -10636,7 +10636,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
@@ -12526,7 +12526,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
esac
;;
- freebsd[12]*)
+ freebsd2.*)
# C++ shared libraries reported to be fairly broken before
# switch to ELF
ld_shlibs_CXX=no
@@ -14301,7 +14301,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -14319,7 +14319,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
diff --git a/libstdc++-v3/doc/xml/faq.xml b/libstdc++-v3/doc/xml/faq.xml
index af9b6da82fe..86142ec9c46 100644
--- a/libstdc++-v3/doc/xml/faq.xml
+++ b/libstdc++-v3/doc/xml/faq.xml
@@ -713,14 +713,15 @@
For those people who are not part of the ISO Library Group
(i.e., nearly all of us needing to read this page in the first
place), a public list of the library defects is occasionally
- published <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/jtc1/sc22/wg21/">here</link>.
+ published on <link xmlns:xlink="http://www.w3.org/1999/xlink"
+ xlink:href="http://www.open-std.org/jtc1/sc22/wg21/">the WG21
+ website</link>.
Some of these issues have resulted in code changes in libstdc++.
</para>
<para>
If you think you've discovered a new bug that is not listed,
- please post a message describing your problem
- to <email>libstdc++@gcc.gnu.org</email> or the Usenet group
- comp.lang.c++.moderated.
+ please post a message describing your problem to the author of
+ the library issues list or the Usenet group comp.lang.c++.moderated.
</para>
</answer>
</qandaentry>
diff --git a/libstdc++-v3/doc/xml/manual/abi.xml b/libstdc++-v3/doc/xml/manual/abi.xml
index a8b92416e89..b79075df36a 100644
--- a/libstdc++-v3/doc/xml/manual/abi.xml
+++ b/libstdc++-v3/doc/xml/manual/abi.xml
@@ -596,8 +596,8 @@ compatible.
</para>
<para>
- Most modern Linux and BSD versions, particularly ones using
- gcc-3.1.x tools and more recent vintages, will meet the
+ Most modern GNU/Linux and BSD versions, particularly ones using
+ GCC 3.1 and later, will meet the
requirements above, as does Solaris 2.5 and up.
</para>
</section>
diff --git a/libstdc++-v3/doc/xml/manual/appendix_contributing.xml b/libstdc++-v3/doc/xml/manual/appendix_contributing.xml
index 49cbcab9ba3..d060f45a6d3 100644
--- a/libstdc++-v3/doc/xml/manual/appendix_contributing.xml
+++ b/libstdc++-v3/doc/xml/manual/appendix_contributing.xml
@@ -45,10 +45,10 @@
two meeting commitment for voting rights, may get a copy of
the standard from their respective national standards
organization. In the USA, this national standards
- organization is ANSI and their web-site is right
- <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.ansi.org">here.</link>
- (And if you've already registered with them, clicking this link will take you to directly to the place where you can
- <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://webstore.ansi.org/RecordDetail.aspx?sku=ISO%2FIEC+14882:2003">buy the standard on-line</link>.)
+ organization is
+ <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.ansi.org">ANSI</link>.
+ (And if you've already registered with them you can
+ <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://webstore.ansi.org/RecordDetail.aspx?sku=INCITS%2fISO%2fIEC+14882-2003">buy the standard on-line</link>.)
</para>
</listitem>
@@ -56,17 +56,16 @@
<para>
The library working group bugs, and known defects, can
be obtained here:
- <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/jtc1/sc22/wg21/">http://www.open-std.org/jtc1/sc22/wg21 </link>
+ <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/jtc1/sc22/wg21/">http://www.open-std.org/jtc1/sc22/wg21</link>
</para>
</listitem>
<listitem>
<para>
The newsgroup dedicated to standardization issues is
- comp.std.c++: this FAQ for this group is quite useful and
- can be
- found <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.comeaucomputing.com/csc/faq.html">
- here </link>.
+ comp.std.c++: the
+ <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.comeaucomputing.com/csc/faq.html">FAQ</link>
+ for this group is quite useful.
</para>
</listitem>
@@ -83,15 +82,15 @@
<para>
Be familiar with the extensions that preceded these
general GNU rules. These style issues for libstdc++ can be
- found <link linkend="contrib.coding_style">here</link>.
+ found in <link linkend="contrib.coding_style">Coding Style</link>.
</para>
</listitem>
<listitem>
<para>
And last but certainly not least, read the
- library-specific information
- found <link linkend="appendix.porting"> here</link>.
+ library-specific information found in
+ <link linkend="appendix.porting">Porting and Maintenance</link>.
</para>
</listitem>
</itemizedlist>
@@ -271,7 +270,7 @@ It has subdirectories:
Files that are used in constructing the library, but are not
installed.
- testsuites/[backward, demangle, ext, performance, thread, 17_* to 27_*]
+ testsuites/[backward, demangle, ext, performance, thread, 17_* to 30_*]
Test programs are here, and may be used to begin to exercise the
library. Support for "make check" and "make check-install" is
complete, and runs through all the subdirectories here when this
diff --git a/libstdc++-v3/doc/xml/manual/backwards_compatibility.xml b/libstdc++-v3/doc/xml/manual/backwards_compatibility.xml
index 525157f1814..f25d3cf5187 100644
--- a/libstdc++-v3/doc/xml/manual/backwards_compatibility.xml
+++ b/libstdc++-v3/doc/xml/manual/backwards_compatibility.xml
@@ -1163,11 +1163,11 @@ AC_DEFUN([AC_HEADER_STDCXX_11], [
#include &lt;fstream&gt;
#include &lt;functional&gt;
#include &lt;future&gt;
+ #include &lt;initializer_list&gt;
#include &lt;iomanip&gt;
#include &lt;ios&gt;
#include &lt;iosfwd&gt;
#include &lt;iostream&gt;
- #include &lt;initializer_list&gt;
#include &lt;istream&gt;
#include &lt;iterator&gt;
#include &lt;limits&gt;
diff --git a/libstdc++-v3/doc/xml/manual/messages.xml b/libstdc++-v3/doc/xml/manual/messages.xml
index d6ce1f7f7a3..4dea4b3738b 100644
--- a/libstdc++-v3/doc/xml/manual/messages.xml
+++ b/libstdc++-v3/doc/xml/manual/messages.xml
@@ -119,8 +119,9 @@ A couple of notes on the standard.
<para>
First, why is <code>messages_base::catalog</code> specified as a typedef
to int? This makes sense for implementations that use
-<code>catopen</code>, but not for others. Fortunately, it's not heavily
-used and so only a minor irritant.
+<code>catopen</code> and define <code>nl_catd</code> as int, but not for
+others. Fortunately, it's not heavily used and so only a minor irritant.
+This has been reported as a possible defect in the standard (LWG 2028).
</para>
<para>
diff --git a/libstdc++-v3/doc/xml/manual/shared_ptr.xml b/libstdc++-v3/doc/xml/manual/shared_ptr.xml
index 6e3392f88ee..be1aaf655f2 100644
--- a/libstdc++-v3/doc/xml/manual/shared_ptr.xml
+++ b/libstdc++-v3/doc/xml/manual/shared_ptr.xml
@@ -95,13 +95,13 @@ until the last weak reference is dropped.
<term><classname>_Sp_counted_base_impl&lt;Ptr, Deleter, Lp&gt;</classname></term>
<listitem>
<para>
-Inherits from _Sp_counted_base and stores a pointer of type <type>Ptr</type>
-and a deleter of type <code>Deleter</code>. <code>_Sp_deleter</code> is
+Inherits from _Sp_counted_base and stores a pointer of type <code>Ptr</code>
+and a deleter of type <code>Deleter</code>. <classname>_Sp_deleter</classname> is
used when the user doesn't supply a custom deleter. Unlike Boost's, this
default deleter is not "checked" because GCC already issues a warning if
<function>delete</function> is used with an incomplete type.
-This is the only derived type used by <classname>shared_ptr&lt;Ptr&gt;</classname>
-and it is never used by <classname>shared_ptr</classname>, which uses one of
+This is the only derived type used by <classname>tr1::shared_ptr&lt;Ptr&gt;</classname>
+and it is never used by <classname>std::shared_ptr</classname>, which uses one of
the following types, depending on how the shared_ptr is constructed.
</para>
</listitem>
@@ -149,11 +149,6 @@ that simplifies the implementation slightly.
</variablelist>
- </section>
-
- <section><info><title>Thread Safety</title></info>
-
-
<para>
C++11-only features are: rvalue-ref/move support, allocator support,
aliasing constructor, make_shared &amp; allocate_shared. Additionally,
@@ -161,6 +156,11 @@ the constructors taking <classname>auto_ptr</classname> parameters are
deprecated in C++11 mode.
</para>
+
+ </section>
+
+ <section><info><title>Thread Safety</title></info>
+
<para>
The
<link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://boost.org/libs/smart_ptr/shared_ptr.htm#ThreadSafety">Thread
@@ -243,7 +243,7 @@ available policies are:
<orderedlist>
<listitem>
<para>
- <type>_S_Atomic</type>
+ <constant>_S_Atomic</constant>
</para>
<para>
Selected when GCC supports a builtin atomic compare-and-swap operation
@@ -256,7 +256,7 @@ synchronisation.
<listitem>
<para>
- <type>_S_Mutex</type>
+ <constant>_S_Mutex</constant>
</para>
<para>
The _Sp_counted_base specialization for this policy contains a mutex,
@@ -267,7 +267,7 @@ builtins aren't available so explicit memory barriers are needed in places.
<listitem>
<para>
- <type>_S_Single</type>
+ <constant>_S_Single</constant>
</para>
<para>
This policy uses a non-reentrant add_ref_lock() with no locking. It is
@@ -285,32 +285,6 @@ used when libstdc++ is built without <literal>--enable-threads</literal>.
</para>
</section>
- <section><info><title>Dual C++11 and TR1 Implementation</title></info>
-
-
-<para>
-The interface of <classname>tr1::shared_ptr</classname> was extended for C++11
-with support for rvalue-references and the other features from N2351.
-The <classname>_Sp_counted_base</classname> base class is implemented in
-<filename>tr1/boost_sp_shared_count.h</filename> and is common to the TR1
-and C++11 versions of <classname>shared_ptr</classname>.
-</para>
-
-<para>
-The classes derived from <classname>_Sp_counted_base</classname> (see Class Hierarchy
-above) and <classname>__shared_count</classname> are implemented separately for C++11
-and TR1, in <filename>bits/shared_ptr.h</filename> and
-<filename>tr1/shared_ptr.h</filename> respectively.
-</para>
-
-<para>
-The TR1 implementation is considered relatively stable, so is unlikely to
-change unless bug fixes require it. If the code that is common to both
-C++11 and TR1 versions needs to diverge further then it might be necessary to
-duplicate <classname>_Sp_counted_base</classname> and only make changes to
-the C++11 version.
-</para>
-</section>
<section><info><title>Related functions and classes</title></info>
@@ -377,34 +351,6 @@ be private.
</section>
-<!--- XXX
- <listitem>
- <type>_Sp_counted_base&lt;Lp&gt;</type>
- <para>
-The base of the hierarchy is parameterized on the lock policy alone.
-_Sp_counted_base doesn't depend on the type of pointer being managed,
-it only maintains the reference counts and calls virtual functions when
-the counts drop to zero. The managed object is destroyed when the last
-strong reference is dropped, but the _Sp_counted_base itself must exist
-until the last weak reference is dropped.
- </para>
- </listitem>
-
- <listitem>
- <type>_Sp_counted_base_impl&lt;Ptr, Deleter, Lp&gt;</type>
- <para>
-Inherits from _Sp_counted_base and stores a pointer of type <code>Ptr</code>
-and a deleter of type <code>Deleter</code>. <code>_Sp_deleter</code> is
-used when the user doesn't supply a custom deleter. Unlike Boost's, this
-default deleter is not "checked" because GCC already issues a warning if
-<code>delete</code> is used with an incomplete type.
-This is the only derived type used by <code>tr1::shared_ptr&lt;Ptr&gt;</code>
-and it is never used by <code>std::shared_ptr</code>, which uses one of
-the following types, depending on how the shared_ptr is constructed.
- </para>
- </listitem>
--->
-
<section xml:id="shared_ptr.using"><info><title>Use</title></info>
diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2011.xml b/libstdc++-v3/doc/xml/manual/status_cxx2011.xml
index 51785fcb812..f47710e3b90 100644
--- a/libstdc++-v3/doc/xml/manual/status_cxx2011.xml
+++ b/libstdc++-v3/doc/xml/manual/status_cxx2011.xml
@@ -384,10 +384,12 @@ particular release.
<entry/>
</row>
<row>
+ <?dbhtml bgcolor="#B0B0B0" ?>
<entry>20.3.2</entry>
<entry>Class template <code>pair</code></entry>
- <entry>Y</entry>
- <entry/>
+ <entry>Partial</entry>
+ <entry>Piecewise construction requires an accessible copy/move
+ constructor.</entry>
</row>
<row>
<entry>20.3.3</entry>
@@ -2136,8 +2138,9 @@ particular release.
<entry>Iostreams base classes</entry>
<entry>Partial</entry>
<entry>
- Missing move and swap operations on <code>basic_ios</code>. Missing
- <code>make_error_code</code> and <code>make_error_condition</code>.
+ Missing move and swap operations on <code>basic_ios</code>.
+ Missing <code>io_errc</code> and <code>iostream_category</code>.
+ <code>ios_base::failure</code> is not derived from <code>system_error</code>.
</entry>
</row>
<row>
@@ -2406,7 +2409,8 @@ particular release.
<entry>30.4.1.3</entry>
<entry>Timed mutex types</entry>
<entry/>
- <entry/>
+ <entry>On POSIX sytems these types are only defined if the OS
+ supports the POSIX Timeouts option. </entry>
</row>
<row>
<entry>30.4.1.3.1</entry>
@@ -2624,5 +2628,59 @@ particular release.
</tgroup>
</table>
+<section xml:id="iso.2011.specific" xreflabel="Implementation Specific"><info><title>Implementation Specific Behavior</title></info>
+
+ <para>For behaviour which is also specified by the 1998 and 2003 standards,
+ see <link linkend="iso.1998.specific">C++ 1998/2003 Implementation
+ Specific Behavior</link>. This section only documents behaviour which
+ is new in the 2011 standard.
+ </para>
+
+ <para>
+ <emphasis>20.8.9.1.3 [func.bind.place]/1</emphasis> There are 29
+ placeholders defined and the placeholder types are
+ <literal>CopyAssignable</literal>.
+ </para>
+
+ <para>
+ <emphasis>30.2.3 [thread.req.native]/1</emphasis>
+ <classname>native_handle_type</classname> and
+ <methodname>native_handle</methodname> are provided. The handle types
+ are defined in terms of the Gthreads abstraction layer.
+ <itemizedlist>
+ <listitem><para><classname>thread</classname>: The native handle type is
+ a typedef for <code>__gthread_t</code> i.e. <code>pthread_t</code>
+ when GCC is configured with the <literal>posix</literal> thread
+ model. The value of the native handle is undefined for a thread
+ which is not joinable.
+ </para></listitem>
+ <listitem><para><classname>mutex</classname> and
+ <classname>timed_mutex</classname>:
+ The native handle type is <code>__gthread_mutex_t*</code> i.e.
+ <code>pthread_mutex_t*</code> for the <literal>posix</literal>
+ thread model.
+ </para></listitem>
+ <listitem><para><classname>recursive_mutex</classname> and
+ <classname>recursive_timed_mutex</classname>:
+ The native handle type is <code>__gthread_recursive_mutex_t*</code>
+ i.e. <code>pthread_mutex_t*</code> for the <literal>posix</literal>
+ thread model.
+ </para></listitem>
+ <listitem><para><classname>condition_variable</classname>: The native
+ handle type is <code>__gthread_cond_t*</code> i.e.
+ <code>pthread_cond_t*</code> for the <literal>posix</literal>
+ thread model.
+ </para></listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ <emphasis>30.6.1 [futures.overview]/2</emphasis>
+ <code>launch</code> is a scoped enumeration type with
+ overloaded operators to support bitmask operations. There are no
+ additional bitmask elements defined.
+ </para>
+
+</section>
</section>
diff --git a/libstdc++-v3/doc/xml/manual/status_cxxtr1.xml b/libstdc++-v3/doc/xml/manual/status_cxxtr1.xml
index 321c4ba269c..58571f2dde7 100644
--- a/libstdc++-v3/doc/xml/manual/status_cxxtr1.xml
+++ b/libstdc++-v3/doc/xml/manual/status_cxxtr1.xml
@@ -1779,4 +1779,20 @@ release.
</tgroup>
</table>
+<section xml:id="iso.tr1.specific" xreflabel="Implementation Specific"><info><title>Implementation Specific Behavior</title></info>
+
+ <para>For behaviour which is specified by the 1998 and 2003 standards,
+ see <link linkend="iso.1998.specific">C++ 1998/2003 Implementation
+ Specific Behavior</link>. This section documents behaviour which
+ is required by TR1.
+ </para>
+
+ <para>
+ <emphasis>3.6.4 [tr.func.bind.place]/1</emphasis> There are 29
+ placeholders defined and the placeholder types are
+ <literal>Assignable</literal>.
+ </para>
+
+</section>
+
</section>
diff --git a/libstdc++-v3/doc/xml/manual/using.xml b/libstdc++-v3/doc/xml/manual/using.xml
index 601ca20d1eb..d2d5e4b2850 100644
--- a/libstdc++-v3/doc/xml/manual/using.xml
+++ b/libstdc++-v3/doc/xml/manual/using.xml
@@ -1269,7 +1269,7 @@ A quick read of the relevant part of the GCC
to display how ad hoc this is: On Solaris, both -pthreads and
-threads (with subtly different meanings) are honored. On OSF,
-pthread and -threads (with subtly different meanings) are
- honored. On GNU/Linux i386, -pthread is honored. On FreeBSD,
+ honored. On GNU/Linux x86, -pthread is honored. On FreeBSD,
-pthread is honored. Some other ports use other switches.
AFAIK, none of this is properly documented anywhere other than
in ``gcc -dumpspecs'' (look at lib and cpp entries).
diff --git a/libstdc++-v3/doc/xml/manual/utilities.xml b/libstdc++-v3/doc/xml/manual/utilities.xml
index 5c3a8fd4864..a60bd34c6d4 100644
--- a/libstdc++-v3/doc/xml/manual/utilities.xml
+++ b/libstdc++-v3/doc/xml/manual/utilities.xml
@@ -25,7 +25,7 @@
<para>If you don't know what functors are, you're not alone. Many people
get slightly the wrong idea. In the interest of not reinventing
the wheel, we will refer you to the introduction to the functor
- concept written by SGI as chapter of their STL, in
+ concept written by SGI as part of their STL, in
<link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.sgi.com/tech/stl/functors.html">their
http://www.sgi.com/tech/stl/functors.html</link>.
</para>
diff --git a/libstdc++-v3/include/backward/binders.h b/libstdc++-v3/include/backward/binders.h
index f98b56aaede..076f8d2e219 100644
--- a/libstdc++-v3/include/backward/binders.h
+++ b/libstdc++-v3/include/backward/binders.h
@@ -80,7 +80,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* The type @c binder2nd and its creator function @c bind2nd do the same
* thing, but the stored argument is passed as the second parameter instead
- * of the first, e.g., @c bind2nd(std::minus<float>,1.3) will create a
+ * of the first, e.g., @c bind2nd(std::minus<float>(),1.3) will create a
* functor whose @c operator() accepts a floating-point number, subtracts
* 1.3 from it, and returns the result. (If @c bind1st had been used,
* the functor would perform <em>1.3 - x</em> instead.
@@ -89,10 +89,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* calling algorithms. Their return values will be temporary objects.
* (The goal is to not require you to type names like
* @c std::binder1st<std::plus<int>> for declaring a variable to hold the
- * return value from @c bind1st(std::plus<int>,5).
+ * return value from @c bind1st(std::plus<int>(),5).
*
* These become more useful when combined with the composition functions.
*
+ * These functions are deprecated in C++11 and can be replaced by
+ * @c std::bind (or @c std::tr1::bind) which is more powerful and flexible,
+ * supporting functions with any number of arguments. Uses of @c bind1st
+ * can be replaced by @c std::bind(f, x, std::placeholders::_1) and
+ * @c bind2nd by @c std::bind(f, std::placeholders::_1, x).
* @{
*/
/// One of the @link binders binder functors@endlink.
diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h
index f0336611d3f..cf292a85385 100644
--- a/libstdc++-v3/include/bits/atomic_base.h
+++ b/libstdc++-v3/include/bits/atomic_base.h
@@ -93,6 +93,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#define LOCKFREE_PROP(T) (__atomic_always_lock_free (sizeof (T), 0) ? 2 : 1)
+#define ATOMIC_BOOL_LOCK_FREE LOCKFREE_PROP (bool)
#define ATOMIC_CHAR_LOCK_FREE LOCKFREE_PROP (char)
#define ATOMIC_CHAR16_T_LOCK_FREE LOCKFREE_PROP (char16_t)
#define ATOMIC_CHAR32_T_LOCK_FREE LOCKFREE_PROP (char32_t)
@@ -101,7 +102,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#define ATOMIC_INT_LOCK_FREE LOCKFREE_PROP (int)
#define ATOMIC_LONG_LOCK_FREE LOCKFREE_PROP (long)
#define ATOMIC_LLONG_LOCK_FREE LOCKFREE_PROP (long long)
-
+#define ATOMIC_POINTER_LOCK_FREE LOCKFREE_PROP (void *)
// Base types for atomics.
template<typename _IntTp>
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 00f9bccd419..169daf58613 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -3044,7 +3044,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __hash_base<size_t, string>
{
size_t
- operator()(const string& __s) const
+ operator()(const string& __s) const noexcept
{ return std::_Hash_impl::hash(__s.data(), __s.length()); }
};
@@ -3055,7 +3055,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __hash_base<size_t, wstring>
{
size_t
- operator()(const wstring& __s) const
+ operator()(const wstring& __s) const noexcept
{ return std::_Hash_impl::hash(__s.data(),
__s.length() * sizeof(wchar_t)); }
};
@@ -3069,7 +3069,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __hash_base<size_t, u16string>
{
size_t
- operator()(const u16string& __s) const
+ operator()(const u16string& __s) const noexcept
{ return std::_Hash_impl::hash(__s.data(),
__s.length() * sizeof(char16_t)); }
};
@@ -3080,7 +3080,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __hash_base<size_t, u32string>
{
size_t
- operator()(const u32string& __s) const
+ operator()(const u32string& __s) const noexcept
{ return std::_Hash_impl::hash(__s.data(),
__s.length() * sizeof(char32_t)); }
};
diff --git a/libstdc++-v3/include/bits/functional_hash.h b/libstdc++-v3/include/bits/functional_hash.h
index e77cb4e17bf..2b82b21f716 100644
--- a/libstdc++-v3/include/bits/functional_hash.h
+++ b/libstdc++-v3/include/bits/functional_hash.h
@@ -66,61 +66,64 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct hash<_Tp*> : public __hash_base<size_t, _Tp*>
{
size_t
- operator()(_Tp* __p) const
+ operator()(_Tp* __p) const noexcept
{ return reinterpret_cast<size_t>(__p); }
};
// Explicit specializations for integer types.
#define _Cxx_hashtable_define_trivial_hash(_Tp) \
template<> \
- inline size_t \
- hash<_Tp>::operator()(_Tp __val) const \
- { return static_cast<size_t>(__val); }
+ struct hash<_Tp> : public __hash_base<size_t, _Tp> \
+ { \
+ size_t \
+ operator()(_Tp __val) const noexcept \
+ { return static_cast<size_t>(__val); } \
+ };
/// Explicit specialization for bool.
- _Cxx_hashtable_define_trivial_hash(bool);
+ _Cxx_hashtable_define_trivial_hash(bool)
/// Explicit specialization for char.
- _Cxx_hashtable_define_trivial_hash(char);
+ _Cxx_hashtable_define_trivial_hash(char)
/// Explicit specialization for signed char.
- _Cxx_hashtable_define_trivial_hash(signed char);
+ _Cxx_hashtable_define_trivial_hash(signed char)
/// Explicit specialization for unsigned char.
- _Cxx_hashtable_define_trivial_hash(unsigned char);
+ _Cxx_hashtable_define_trivial_hash(unsigned char)
/// Explicit specialization for wchar_t.
- _Cxx_hashtable_define_trivial_hash(wchar_t);
+ _Cxx_hashtable_define_trivial_hash(wchar_t)
/// Explicit specialization for char16_t.
- _Cxx_hashtable_define_trivial_hash(char16_t);
+ _Cxx_hashtable_define_trivial_hash(char16_t)
/// Explicit specialization for char32_t.
- _Cxx_hashtable_define_trivial_hash(char32_t);
+ _Cxx_hashtable_define_trivial_hash(char32_t)
/// Explicit specialization for short.
- _Cxx_hashtable_define_trivial_hash(short);
+ _Cxx_hashtable_define_trivial_hash(short)
/// Explicit specialization for int.
- _Cxx_hashtable_define_trivial_hash(int);
+ _Cxx_hashtable_define_trivial_hash(int)
/// Explicit specialization for long.
- _Cxx_hashtable_define_trivial_hash(long);
+ _Cxx_hashtable_define_trivial_hash(long)
/// Explicit specialization for long long.
- _Cxx_hashtable_define_trivial_hash(long long);
+ _Cxx_hashtable_define_trivial_hash(long long)
/// Explicit specialization for unsigned short.
- _Cxx_hashtable_define_trivial_hash(unsigned short);
+ _Cxx_hashtable_define_trivial_hash(unsigned short)
/// Explicit specialization for unsigned int.
- _Cxx_hashtable_define_trivial_hash(unsigned int);
+ _Cxx_hashtable_define_trivial_hash(unsigned int)
/// Explicit specialization for unsigned long.
- _Cxx_hashtable_define_trivial_hash(unsigned long);
+ _Cxx_hashtable_define_trivial_hash(unsigned long)
/// Explicit specialization for unsigned long long.
- _Cxx_hashtable_define_trivial_hash(unsigned long long);
+ _Cxx_hashtable_define_trivial_hash(unsigned long long)
#undef _Cxx_hashtable_define_trivial_hash
@@ -162,26 +165,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Specialization for float.
template<>
- inline size_t
- hash<float>::operator()(float __val) const
+ struct hash<float> : public __hash_base<size_t, float>
{
- // 0 and -0 both hash to zero.
- return __val != 0.0f ? std::_Hash_impl::hash(__val) : 0;
- }
+ size_t
+ operator()(float __val) const noexcept
+ {
+ // 0 and -0 both hash to zero.
+ return __val != 0.0f ? std::_Hash_impl::hash(__val) : 0;
+ }
+ };
/// Specialization for double.
template<>
- inline size_t
- hash<double>::operator()(double __val) const
+ struct hash<double> : public __hash_base<size_t, double>
{
- // 0 and -0 both hash to zero.
- return __val != 0.0 ? std::_Hash_impl::hash(__val) : 0;
- }
+ size_t
+ operator()(double __val) const noexcept
+ {
+ // 0 and -0 both hash to zero.
+ return __val != 0.0 ? std::_Hash_impl::hash(__val) : 0;
+ }
+ };
/// Specialization for long double.
template<>
- _GLIBCXX_PURE size_t
- hash<long double>::operator()(long double __val) const;
+ struct hash<long double>
+ : public __hash_base<size_t, long double>
+ {
+ _GLIBCXX_PURE size_t
+ operator()(long double __val) const noexcept;
+ };
// @} group hashes
diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index 95d06b21262..dfa91f7cc8c 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -48,7 +48,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// value type is Value. As a conforming extension, we allow for
// value type != Value.
- // _ExtractKey: function object that takes a object of type Value
+ // _ExtractKey: function object that takes an object of type Value
// and returns a value of type _Key.
// _Equal: function object that takes two objects of type k and returns
@@ -78,9 +78,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// count. If so, returns make_pair(true, n), where n is the new
// bucket count. If not, returns make_pair(false, <anything>).
- // ??? Right now it is hard-wired that the number of buckets never
- // shrinks. Should we allow _RehashPolicy to change that?
-
// __cache_hash_code: bool. true if we store the value of the hash
// function along with the value. This is a time-space tradeoff.
// Storing it may improve lookup speed by reducing the number of times
@@ -94,6 +91,53 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// is always at most one, false if it may be an arbitrary number. This
// true for unordered_set and unordered_map, false for unordered_multiset
// and unordered_multimap.
+ /**
+ * Here's _Hashtable data structure, each _Hashtable has:
+ * - _Bucket[] _M_buckets
+ * - size_type _M_bucket_count
+ * - size_type _M_begin_bucket_index
+ * - size_type _M_element_count
+ *
+ * with _Bucket being _Node* and _Node:
+ * - _Node* _M_next
+ * - Tp _M_value
+ * - size_t _M_code if cache_hash_code is true
+ *
+ * In terms of Standard containers the hastable is like the aggregation of:
+ * - std::forward_list<_Node> containing the elements
+ * - std::vector<std::forward_list<_Node>::iterator> representing the buckets
+ *
+ * The first non-empty bucket with index _M_begin_bucket_index contains the
+ * first container node which is also the first bucket node whereas other
+ * non-empty buckets contain the node before the first bucket node. This is so
+ * to implement something like a std::forward_list::erase_after on container
+ * erase calls.
+ *
+ * Access to the bucket last element require a check on the hash code to see
+ * if the node is still in the bucket. Such a design impose a quite efficient
+ * hash functor and is one of the reasons it is highly advise to set
+ * __cache_hash_code to true.
+ *
+ * The container iterators are simply built from nodes. This way incrementing
+ * the iterator is perfectly efficient no matter how many empty buckets there
+ * are in the container.
+ *
+ * On insert we compute element hash code and thanks to it find the bucket
+ * index. If the element is the first one in the bucket we must find the
+ * previous non-empty bucket where the previous node rely. To keep this loop
+ * minimal it is important that the number of bucket is not too high compared
+ * to the number of elements. So the hash policy must be carefully design so
+ * that it computes a bucket count large enough to respect the user defined
+ * load factor but also not too large to limit impact on the insert operation.
+ *
+ * On erase, the simple iterator design impose to use the hash functor to get
+ * the index of the bucket to update. For this reason, when __cache_hash_code
+ * is set to false, there is a static assertion that the hash functor cannot
+ * throw.
+ *
+ * _M_begin_bucket_index is used to offer contant time access to the container
+ * begin iterator.
+ */
template<typename _Key, typename _Value, typename _Allocator,
typename _ExtractKey, typename _Equal,
@@ -130,6 +174,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__constant_iterators,
__unique_keys> >
{
+ static_assert(__or_<integral_constant<bool, __cache_hash_code>,
+ __detail::__is_noexcept_hash<_Key, _H1>>::value,
+ "Cache the hash code or qualify your hash functor with noexcept");
public:
typedef _Allocator allocator_type;
typedef _Value value_type;
@@ -152,30 +199,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__cache_hash_code>
const_local_iterator;
- typedef __detail::_Hashtable_iterator<value_type, __constant_iterators,
- __cache_hash_code>
- iterator;
- typedef __detail::_Hashtable_const_iterator<value_type,
- __constant_iterators,
- __cache_hash_code>
- const_iterator;
+ typedef local_iterator iterator;
+ typedef const_local_iterator const_iterator;
template<typename _Key2, typename _Value2, typename _Ex2, bool __unique2,
typename _Hashtable2>
friend struct __detail::_Map_base;
private:
+ typedef typename _RehashPolicy::_State _RehashPolicyState;
typedef __detail::_Hash_node<_Value, __cache_hash_code> _Node;
typedef typename _Allocator::template rebind<_Node>::other
_Node_allocator_type;
- typedef typename _Allocator::template rebind<_Node*>::other
+ typedef _Node* _Bucket;
+ //typedef __detail::_Bucket<_Value, __cache_hash_code> _Bucket;
+ typedef typename _Allocator::template rebind<_Bucket>::other
_Bucket_allocator_type;
typedef typename _Allocator::template rebind<_Value>::other
_Value_allocator_type;
_Node_allocator_type _M_node_allocator;
- _Node** _M_buckets;
+ _Bucket* _M_buckets;
size_type _M_bucket_count;
size_type _M_begin_bucket_index; // First non-empty bucket.
size_type _M_element_count;
@@ -188,14 +233,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
_M_deallocate_node(_Node* __n);
+ // Deallocate all nodes contained in the bucket array, buckets' nodes
+ // are not linked to each other
+ void
+ _M_deallocate_nodes(_Bucket*, size_type);
+
+ // Deallocate the linked list of nodes pointed to by __n
void
- _M_deallocate_nodes(_Node**, size_type);
+ _M_deallocate_nodes(_Node* __n);
- _Node**
+ _Bucket*
_M_allocate_buckets(size_type __n);
void
- _M_deallocate_buckets(_Node**, size_type __n);
+ _M_deallocate_buckets(_Bucket*, size_type __n);
+
+ // Gets bucket begin dealing with the difference between first non-empty
+ // bucket containing the first container node and the other non-empty
+ // buckets containing the node before the one belonging to the bucket.
+ _Node*
+ _M_bucket_begin(size_type __bkt) const;
+
+ // Gets the bucket last node if any
+ _Node*
+ _M_bucket_end(size_type __bkt) const;
+
+ // Gets the bucket node after the last if any
+ _Node*
+ _M_bucket_past_the_end(size_type __bkt) const
+ {
+ _Node* __end = _M_bucket_end(__bkt);
+ return __end ? __end->_M_next : nullptr;
+ }
public:
// Constructor, destructor, assignment, swap
@@ -240,27 +309,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Basic container operations
iterator
begin() noexcept
- { return iterator(_M_buckets + _M_begin_bucket_index); }
+ { return iterator(_M_buckets[_M_begin_bucket_index]); }
const_iterator
begin() const noexcept
- { return const_iterator(_M_buckets + _M_begin_bucket_index); }
+ { return const_iterator(_M_buckets[_M_begin_bucket_index]); }
iterator
end() noexcept
- { return iterator(_M_buckets + _M_bucket_count); }
+ { return iterator(nullptr); }
const_iterator
end() const noexcept
- { return const_iterator(_M_buckets + _M_bucket_count); }
+ { return const_iterator(nullptr); }
const_iterator
cbegin() const noexcept
- { return const_iterator(_M_buckets + _M_begin_bucket_index); }
+ { return const_iterator(_M_buckets[_M_begin_bucket_index]); }
const_iterator
cend() const noexcept
- { return const_iterator(_M_buckets + _M_bucket_count); }
+ { return const_iterator(nullptr); }
size_type
size() const noexcept
@@ -307,28 +376,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
local_iterator
begin(size_type __n)
- { return local_iterator(_M_buckets[__n]); }
+ { return local_iterator(_M_bucket_begin(__n)); }
local_iterator
- end(size_type)
- { return local_iterator(0); }
+ end(size_type __n)
+ { return local_iterator(_M_bucket_past_the_end(__n)); }
const_local_iterator
begin(size_type __n) const
- { return const_local_iterator(_M_buckets[__n]); }
+ { return const_local_iterator(_M_bucket_begin(__n)); }
const_local_iterator
- end(size_type) const
- { return const_local_iterator(0); }
+ end(size_type __n) const
+ { return const_local_iterator(_M_bucket_past_the_end(__n)); }
// DR 691.
const_local_iterator
cbegin(size_type __n) const
- { return const_local_iterator(_M_buckets[__n]); }
+ { return const_local_iterator(_M_bucket_begin(__n)); }
const_local_iterator
- cend(size_type) const
- { return const_local_iterator(0); }
+ cend(size_type __n) const
+ { return const_local_iterator(_M_bucket_past_the_end(__n)); }
float
load_factor() const noexcept
@@ -366,9 +435,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
private:
// Find and insert helper functions and types
_Node*
- _M_find_node(_Node*, const key_type&,
+ _M_find_node(size_type, const key_type&,
typename _Hashtable::_Hash_code_type) const;
+ // Insert a node in an empty bucket
+ void
+ _M_insert_bucket_begin(size_type, _Node*);
+
+ // Insert a node after an other one in a non-empty bucket
+ void
+ _M_insert_after(size_type, _Node*, _Node*);
+
+ // Remove the bucket first node
+ void
+ _M_remove_bucket_begin(size_type __bkt, _Node* __next_n,
+ size_type __next_bkt);
+
+ // Get the node before __n in the bucket __bkt
+ _Node*
+ _M_get_previous_node(size_type __bkt, _Node* __n);
+
template<typename _Arg>
iterator
_M_insert_bucket(_Arg&&, size_type,
@@ -432,6 +518,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
iterator
erase(const_iterator);
+ // LWG 2059.
+ iterator
+ erase(iterator __it)
+ { return erase(const_iterator(__it)); }
+
size_type
erase(const key_type&);
@@ -449,8 +540,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
private:
// Unconditionally change size of bucket array to n, restore hash policy
- // resize value to __next_resize on exception.
- void _M_rehash(size_type __n, size_type __next_resize);
+ // state to __state on exception.
+ void _M_rehash(size_type __n, const _RehashPolicyState& __state);
};
@@ -471,7 +562,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__try
{
_M_node_allocator.construct(__n, std::forward<_Args>(__args)...);
- __n->_M_next = 0;
return __n;
}
__catch(...)
@@ -501,18 +591,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
- _M_deallocate_nodes(_Node** __array, size_type __n)
+ _M_deallocate_nodes(_Bucket* __buckets, size_type __n)
+ {
+ for (size_type __i = 0; __i != __n; ++__i)
+ _M_deallocate_nodes(__buckets[__i]);
+ }
+
+ template<typename _Key, typename _Value,
+ typename _Allocator, typename _ExtractKey, typename _Equal,
+ typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
+ bool __chc, bool __cit, bool __uk>
+ void
+ _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
+ _M_deallocate_nodes(_Node* __n)
{
- for (size_type __i = 0; __i < __n; ++__i)
+ while (__n)
{
- _Node* __p = __array[__i];
- while (__p)
- {
- _Node* __tmp = __p;
- __p = __p->_M_next;
- _M_deallocate_node(__tmp);
- }
- __array[__i] = 0;
+ _Node* __tmp = __n;
+ __n = __n->_M_next;
+ _M_deallocate_node(__tmp);
}
}
@@ -522,18 +620,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
bool __chc, bool __cit, bool __uk>
typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy,
- __chc, __cit, __uk>::_Node**
+ __chc, __cit, __uk>::_Bucket*
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
_M_allocate_buckets(size_type __n)
{
_Bucket_allocator_type __alloc(_M_node_allocator);
- // We allocate one extra bucket to hold a sentinel, an arbitrary
- // non-null pointer. Iterator increment relies on this.
- _Node** __p = __alloc.allocate(__n + 1);
- std::fill(__p, __p + __n, (_Node*) 0);
- __p[__n] = reinterpret_cast<_Node*>(0x1000);
+ // We allocate one extra bucket to have _M_begin_bucket_index
+ // point to it as long as container is empty
+ _Bucket* __p = __alloc.allocate(__n + 1);
+ __builtin_memset(__p, 0, (__n + 1) * sizeof(_Bucket));
return __p;
}
@@ -544,7 +641,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
- _M_deallocate_buckets(_Node** __p, size_type __n)
+ _M_deallocate_buckets(_Bucket* __p, size_type __n)
{
_Bucket_allocator_type __alloc(_M_node_allocator);
__alloc.deallocate(__p, __n + 1);
@@ -554,6 +651,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename _Allocator, typename _ExtractKey, typename _Equal,
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool __chc, bool __cit, bool __uk>
+ typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey,
+ _Equal, _H1, _H2, _Hash, _RehashPolicy,
+ __chc, __cit, __uk>::_Node*
+ _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
+ _M_bucket_begin(size_type __bkt) const
+ {
+ if (__bkt == _M_begin_bucket_index)
+ return _M_buckets[__bkt];
+ _Node* __n = _M_buckets[__bkt];
+ return __n ? __n->_M_next : nullptr;
+ }
+
+ template<typename _Key, typename _Value,
+ typename _Allocator, typename _ExtractKey, typename _Equal,
+ typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
+ bool __chc, bool __cit, bool __uk>
+ typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey,
+ _Equal, _H1, _H2, _Hash, _RehashPolicy,
+ __chc, __cit, __uk>::_Node*
+ _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
+ _M_bucket_end(size_type __bkt) const
+ {
+ _Node* __n = _M_bucket_begin(__bkt);
+ if (__n)
+ for (;; __n = __n->_M_next)
+ if (!__n->_M_next
+ || this->_M_bucket_index(__n->_M_next, _M_bucket_count)
+ != __bkt)
+ break;
+ return __n;
+ }
+
+ template<typename _Key, typename _Value,
+ typename _Allocator, typename _ExtractKey, typename _Equal,
+ typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
+ bool __chc, bool __cit, bool __uk>
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
_Hashtable(size_type __bucket_hint,
@@ -571,6 +706,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_rehash_policy()
{
_M_bucket_count = _M_rehash_policy._M_next_bkt(__bucket_hint);
+ // We don't want the rehash policy to ask for the hashtable to shrink
+ // on the first insertion so we need to reset its previous resize level.
+ _M_rehash_policy._M_prev_resize = 0;
_M_buckets = _M_allocate_buckets(_M_bucket_count);
_M_begin_bucket_index = _M_bucket_count;
}
@@ -602,6 +740,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_bkt_for_elements(__detail::
__distance_fw(__f,
__l)));
+ // We don't want the rehash policy to ask for the hashtable to shrink
+ // on the first insertion so we need to reset its previous resize
+ // level.
+ _M_rehash_policy._M_prev_resize = 0;
_M_buckets = _M_allocate_buckets(_M_bucket_count);
_M_begin_bucket_index = _M_bucket_count;
__try
@@ -637,17 +779,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_buckets = _M_allocate_buckets(_M_bucket_count);
__try
{
- for (size_type __i = 0; __i < __ht._M_bucket_count; ++__i)
+ const _Node* __ht_n = __ht._M_buckets[__ht._M_begin_bucket_index];
+ if (!__ht_n)
+ return;
+
+ // Note that the copy constructor do not rely on hash code usage.
+ // First deal with the special first node that is directly store in
+ // the first non-empty bucket
+ _Node* __this_n = _M_allocate_node(__ht_n->_M_v);
+ this->_M_copy_code(__this_n, __ht_n);
+ _M_buckets[_M_begin_bucket_index] = __this_n;
+ __ht_n = __ht_n->_M_next;
+ // Second deal with following non-empty buckets containing previous
+ // nodes node.
+ for (size_type __i = __ht._M_begin_bucket_index + 1;
+ __i != __ht._M_bucket_count; ++__i)
{
- _Node* __n = __ht._M_buckets[__i];
- _Node** __tail = _M_buckets + __i;
- while (__n)
+ if (!__ht._M_buckets[__i])
+ continue;
+
+ for (; __ht_n != __ht._M_buckets[__i]->_M_next;
+ __ht_n = __ht_n->_M_next)
{
- *__tail = _M_allocate_node(__n->_M_v);
- this->_M_copy_code(*__tail, __n);
- __tail = &((*__tail)->_M_next);
- __n = __n->_M_next;
+ __this_n->_M_next = _M_allocate_node(__ht_n->_M_v);
+ this->_M_copy_code(__this_n->_M_next, __ht_n);
+ __this_n = __this_n->_M_next;
}
+
+ _M_buckets[__i] = __this_n;
+ }
+ // Last finalize copy of the nodes of the last non-empty bucket
+ for (; __ht_n; __ht_n = __ht_n->_M_next)
+ {
+ __this_n->_M_next = _M_allocate_node(__ht_n->_M_v);
+ this->_M_copy_code(__this_n->_M_next, __ht_n);
+ __this_n = __this_n->_M_next;
}
}
__catch(...)
@@ -732,8 +898,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__rehash_policy(const _RehashPolicy& __pol)
{
size_type __n_bkt = __pol._M_bkt_for_elements(_M_element_count);
- if (__n_bkt > _M_bucket_count)
- _M_rehash(__n_bkt, _M_rehash_policy._M_next_resize);
+ if (__n_bkt != _M_bucket_count)
+ _M_rehash(__n_bkt, _M_rehash_policy._M_state());
_M_rehash_policy = __pol;
}
@@ -750,8 +916,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
- _Node* __p = _M_find_node(_M_buckets[__n], __k, __code);
- return __p ? iterator(__p, _M_buckets + __n) : this->end();
+ _Node* __p = _M_find_node(__n, __k, __code);
+ return __p ? iterator(__p) : this->end();
}
template<typename _Key, typename _Value,
@@ -767,8 +933,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
- _Node* __p = _M_find_node(_M_buckets[__n], __k, __code);
- return __p ? const_iterator(__p, _M_buckets + __n) : this->end();
+ _Node* __p = _M_find_node(__n, __k, __code);
+ return __p ? const_iterator(__p) : this->end();
}
template<typename _Key, typename _Value,
@@ -784,10 +950,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
+ _Node* __p = _M_bucket_begin(__n);
+ if (!__p)
+ return 0;
+
std::size_t __result = 0;
- for (_Node* __p = _M_buckets[__n]; __p; __p = __p->_M_next)
- if (this->_M_compare(__k, __code, __p))
- ++__result;
+ for (;; __p = __p->_M_next)
+ {
+ if (this->_M_compare(__k, __code, __p))
+ ++__result;
+ else if (__result)
+ // All equivalent values are next to each other, if we found a not
+ // equivalent value after an equivalent one it means that we won't
+ // find anymore an equivalent value.
+ break;
+ if (!__p->_M_next
+ || this->_M_bucket_index(__p->_M_next, _M_bucket_count)
+ != __n)
+ break;
+ }
return __result;
}
@@ -809,21 +990,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
- _Node** __head = _M_buckets + __n;
- _Node* __p = _M_find_node(*__head, __k, __code);
+ _Node* __p = _M_find_node(__n, __k, __code);
if (__p)
{
_Node* __p1 = __p->_M_next;
- for (; __p1; __p1 = __p1->_M_next)
- if (!this->_M_compare(__k, __code, __p1))
- break;
+ while (__p1
+ && this->_M_bucket_index(__p1, _M_bucket_count) == __n
+ && this->_M_compare(__k, __code, __p1))
+ __p1 = __p1->_M_next;
- iterator __first(__p, __head);
- iterator __last(__p1, __head);
- if (!__p1)
- __last._M_incr_bucket();
- return std::make_pair(__first, __last);
+ return std::make_pair(iterator(__p), iterator(__p1));
}
else
return std::make_pair(this->end(), this->end());
@@ -847,28 +1024,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
- _Node** __head = _M_buckets + __n;
- _Node* __p = _M_find_node(*__head, __k, __code);
+ _Node* __p = _M_find_node(__n, __k, __code);
if (__p)
{
_Node* __p1 = __p->_M_next;
- for (; __p1; __p1 = __p1->_M_next)
- if (!this->_M_compare(__k, __code, __p1))
- break;
+ while (__p1
+ && this->_M_bucket_index(__p1, _M_bucket_count) == __n
+ && this->_M_compare(__k, __code, __p1))
+ __p1 = __p1->_M_next;
- const_iterator __first(__p, __head);
- const_iterator __last(__p1, __head);
- if (!__p1)
- __last._M_incr_bucket();
- return std::make_pair(__first, __last);
+ return std::make_pair(const_iterator(__p), const_iterator(__p1));
}
else
return std::make_pair(this->end(), this->end());
}
- // Find the node whose key compares equal to k, beginning the search
- // at p (usually the head of a bucket). Return nil if no node is found.
+ // Find the node whose key compares equal to k in the bucket n. Return nullptr
+ // if no node is found.
template<typename _Key, typename _Value,
typename _Allocator, typename _ExtractKey, typename _Equal,
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
@@ -878,13 +1051,131 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__chc, __cit, __uk>::_Node*
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
- _M_find_node(_Node* __p, const key_type& __k,
+ _M_find_node(size_type __n, const key_type& __k,
typename _Hashtable::_Hash_code_type __code) const
{
- for (; __p; __p = __p->_M_next)
- if (this->_M_compare(__k, __code, __p))
- return __p;
- return false;
+ _Node* __p = _M_bucket_begin(__n);
+ if (!__p)
+ return nullptr;
+ for (;; __p = __p->_M_next)
+ {
+ if (this->_M_compare(__k, __code, __p))
+ return __p;
+ if (!(__p->_M_next)
+ || this->_M_bucket_index(__p->_M_next, _M_bucket_count) != __n)
+ break;
+ }
+ return nullptr;
+ }
+
+ template<typename _Key, typename _Value,
+ typename _Allocator, typename _ExtractKey, typename _Equal,
+ typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
+ bool __chc, bool __cit, bool __uk>
+ void
+ _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
+ _M_insert_bucket_begin(size_type __bkt, _Node* __new_node)
+ {
+ _Node* __prev_n;
+ if (__bkt < _M_begin_bucket_index)
+ {
+ if (_M_begin_bucket_index != _M_bucket_count)
+ {
+ __new_node->_M_next = _M_buckets[_M_begin_bucket_index];
+ _M_buckets[_M_begin_bucket_index] = __new_node;
+ }
+ __prev_n = __new_node;
+ _M_begin_bucket_index = __bkt;
+ }
+ else
+ {
+ // We need to find previous non-empty bucket to link the new node.
+ // There are several ways to find this previous bucket:
+ // 1. Move backward until we find it (the current method)
+ // 2. Start from the begin bucket index and move forward until we
+ // cross __n position.
+ // 3. Move forward until we find a non-empty bucket that will
+ // contain the previous node.
+ size_type __prev_bkt;
+ for (__prev_bkt = __bkt; __prev_bkt-- != 0;)
+ if (_M_buckets[__prev_bkt])
+ break;
+ __prev_n = _M_bucket_end(__prev_bkt);
+ _M_insert_after(__prev_bkt, __prev_n, __new_node);
+ }
+ _M_buckets[__bkt] = __prev_n;
+ }
+
+ template<typename _Key, typename _Value,
+ typename _Allocator, typename _ExtractKey, typename _Equal,
+ typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
+ bool __chc, bool __cit, bool __uk>
+ void
+ _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
+ _M_insert_after(size_type __bkt, _Node* __prev_n, _Node* __new_n)
+ {
+ if (__prev_n->_M_next)
+ {
+ size_type __next_bkt =
+ this->_M_bucket_index(__prev_n->_M_next, _M_bucket_count);
+ if (__next_bkt != __bkt)
+ _M_buckets[__next_bkt] = __new_n;
+ }
+ __new_n->_M_next = __prev_n->_M_next;
+ __prev_n->_M_next = __new_n;
+ }
+
+ template<typename _Key, typename _Value,
+ typename _Allocator, typename _ExtractKey, typename _Equal,
+ typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
+ bool __chc, bool __cit, bool __uk>
+ void
+ _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
+ _M_remove_bucket_begin(size_type __bkt, _Node* __next, size_type __next_bkt)
+ {
+ if (!__next || __next_bkt != __bkt)
+ {
+ // Bucket is now empty
+ if (__next && __next_bkt != __bkt)
+ // Update next non-empty bucket before begin node
+ _M_buckets[__next_bkt] = _M_buckets[__bkt];
+ _M_buckets[__bkt] = nullptr;
+ if (__bkt == _M_begin_bucket_index)
+ // We need to update begin bucket index
+ if (__next)
+ {
+ _M_begin_bucket_index = __next_bkt;
+ _M_buckets[_M_begin_bucket_index] = __next;
+ }
+ else
+ _M_begin_bucket_index = _M_bucket_count;
+ }
+ else if (__bkt == _M_begin_bucket_index)
+ _M_buckets[__bkt] = __next;
+ }
+
+ template<typename _Key, typename _Value,
+ typename _Allocator, typename _ExtractKey, typename _Equal,
+ typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
+ bool __chc, bool __cit, bool __uk>
+ typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey,
+ _Equal, _H1, _H2, _Hash, _RehashPolicy,
+ __chc, __cit, __uk>::_Node*
+ _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
+ _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
+ _M_get_previous_node(size_type __bkt, _Node* __n)
+ {
+ _Node* __prev_n = nullptr;
+ if (__bkt != _M_begin_bucket_index || __n != _M_buckets[__bkt])
+ {
+ __prev_n = _M_buckets[__bkt];
+ while (__prev_n->_M_next != __n)
+ __prev_n = __prev_n->_M_next;
+ }
+ return __prev_n;
}
// Insert v in bucket n (assumes no element with its key already present).
@@ -901,7 +1192,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_insert_bucket(_Arg&& __v, size_type __n,
typename _Hashtable::_Hash_code_type __code)
{
- const size_type __saved_next_resize = _M_rehash_policy._M_next_resize;
+ const _RehashPolicyState& __saved_state = _M_rehash_policy._M_state();
std::pair<bool, std::size_t> __do_rehash
= _M_rehash_policy._M_need_rehash(_M_bucket_count,
_M_element_count, 1);
@@ -912,27 +1203,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__n = this->_M_bucket_index(__k, __code, __do_rehash.second);
}
- _Node* __new_node = 0;
+ _Node* __new_node = nullptr;
__try
{
// Allocate the new node before doing the rehash so that we
// don't do a rehash if the allocation throws.
__new_node = _M_allocate_node(std::forward<_Arg>(__v));
+ this->_M_store_code(__new_node, __code);
if (__do_rehash.first)
- _M_rehash(__do_rehash.second, __saved_next_resize);
+ _M_rehash(__do_rehash.second, __saved_state);
- __new_node->_M_next = _M_buckets[__n];
- this->_M_store_code(__new_node, __code);
- _M_buckets[__n] = __new_node;
+ if (_M_buckets[__n])
+ _M_insert_after(__n, _M_buckets[__n], __new_node);
+ else
+ _M_insert_bucket_begin(__n, __new_node);
++_M_element_count;
- if (__n < _M_begin_bucket_index)
- _M_begin_bucket_index = __n;
- return iterator(__new_node, _M_buckets + __n);
+ return iterator(__new_node);
}
__catch(...)
{
if (!__new_node)
- _M_rehash_policy._M_next_resize = __saved_next_resize;
+ _M_rehash_policy._M_reset(__saved_state);
else
_M_deallocate_node(__new_node);
__throw_exception_again;
@@ -957,8 +1248,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
- if (_Node* __p = _M_find_node(_M_buckets[__n], __k, __code))
- return std::make_pair(iterator(__p, _M_buckets + __n), false);
+ if (_Node* __p = _M_find_node(__n, __k, __code))
+ return std::make_pair(iterator(__p), false);
return std::make_pair(_M_insert_bucket(std::forward<_Arg>(__v),
__n, __code), true);
}
@@ -976,37 +1267,58 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
_M_insert(_Arg&& __v, std::false_type)
{
- const size_type __saved_next_resize = _M_rehash_policy._M_next_resize;
+ const _RehashPolicyState& __saved_state = _M_rehash_policy._M_state();
std::pair<bool, std::size_t> __do_rehash
= _M_rehash_policy._M_need_rehash(_M_bucket_count,
_M_element_count, 1);
- if (__do_rehash.first)
- _M_rehash(__do_rehash.second, __saved_next_resize);
const key_type& __k = this->_M_extract(__v);
typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
// First find the node, avoid leaking new_node if compare throws.
- _Node* __prev = _M_find_node(_M_buckets[__n], __k, __code);
- _Node* __new_node = _M_allocate_node(std::forward<_Arg>(__v));
-
- if (__prev)
+ _Node* __prev = _M_find_node(__n, __k, __code);
+ _Node* __new_node = nullptr;
+ __try
{
- __new_node->_M_next = __prev->_M_next;
- __prev->_M_next = __new_node;
+ // Second allocate new node so that we don't rehash if it throws
+ __new_node = _M_allocate_node(std::forward<_Arg>(__v));
+ this->_M_store_code(__new_node, __code);
+ if (__do_rehash.first)
+ {
+ _M_rehash(__do_rehash.second, __saved_state);
+ __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
+ // __prev is still valid because rehash do not invalidate nodes
+ }
+
+ if (__prev)
+ // Insert after the previous equivalent node
+ _M_insert_after(__n, __prev, __new_node);
+ else if (_M_buckets[__n])
+ // Bucket is not empty and the inserted node has no equivalent in
+ // the hashtable. We must insert the new node at the beginning or
+ // end of the bucket to preserve equivalent elements relative
+ // positions.
+ if (__n != _M_begin_bucket_index)
+ // We insert the new node at the beginning
+ _M_insert_after(__n, _M_buckets[__n], __new_node);
+ else
+ // We insert the new node at the end
+ _M_insert_after(__n, _M_bucket_end(__n), __new_node);
+ else
+ _M_insert_bucket_begin(__n, __new_node);
+ ++_M_element_count;
+ return iterator(__new_node);
}
- else
+ __catch(...)
{
- __new_node->_M_next = _M_buckets[__n];
- _M_buckets[__n] = __new_node;
- if (__n < _M_begin_bucket_index)
- _M_begin_bucket_index = __n;
+ if (!__new_node)
+ _M_rehash_policy._M_reset(__saved_state);
+ else
+ _M_deallocate_node(__new_node);
+ __throw_exception_again;
}
- this->_M_store_code(__new_node, __code);
- ++_M_element_count;
- return iterator(__new_node, _M_buckets + __n);
}
template<typename _Key, typename _Value,
@@ -1020,12 +1332,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
insert(_InputIterator __first, _InputIterator __last)
{
size_type __n_elt = __detail::__distance_fw(__first, __last);
- const size_type __saved_next_resize = _M_rehash_policy._M_next_resize;
+ const _RehashPolicyState& __saved_state = _M_rehash_policy._M_state();
std::pair<bool, std::size_t> __do_rehash
= _M_rehash_policy._M_need_rehash(_M_bucket_count,
_M_element_count, __n_elt);
if (__do_rehash.first)
- _M_rehash(__do_rehash.second, __saved_next_resize);
+ _M_rehash(__do_rehash.second, __saved_state);
for (; __first != __last; ++__first)
this->insert(*__first);
@@ -1042,31 +1354,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
erase(const_iterator __it)
{
- iterator __result(__it._M_cur_node, __it._M_cur_bucket);
- ++__result;
-
- _Node* __cur = *__it._M_cur_bucket;
- if (__cur == __it._M_cur_node)
+ _Node* __n = __it._M_cur;
+ std::size_t __bkt = this->_M_bucket_index(__n, _M_bucket_count);
+
+ // Look for previous node to unlink it from the erased one, this is why
+ // we need buckets to contain the before begin node of the bucket to make
+ // this research fast.
+ _Node* __prev_n = _M_get_previous_node(__bkt, __n);
+ if (__n == _M_bucket_begin(__bkt))
+ _M_remove_bucket_begin(__bkt, __n->_M_next,
+ __n->_M_next ? this->_M_bucket_index(__n->_M_next, _M_bucket_count)
+ : 0);
+ else if (__n->_M_next)
{
- *__it._M_cur_bucket = __cur->_M_next;
-
- // If _M_begin_bucket_index no longer indexes the first non-empty
- // bucket - its single node is being erased - update it.
- if (!_M_buckets[_M_begin_bucket_index])
- _M_begin_bucket_index = __result._M_cur_bucket - _M_buckets;
- }
- else
- {
- _Node* __next = __cur->_M_next;
- while (__next != __it._M_cur_node)
- {
- __cur = __next;
- __next = __cur->_M_next;
- }
- __cur->_M_next = __next->_M_next;
+ size_type __next_bkt =
+ this->_M_bucket_index(__n->_M_next, _M_bucket_count);
+ if (__next_bkt != __bkt)
+ _M_buckets[__next_bkt] = __prev_n;
}
- _M_deallocate_node(__it._M_cur_node);
+ if (__prev_n)
+ __prev_n->_M_next = __n->_M_next;
+ iterator __result(__n->_M_next);
+ _M_deallocate_node(__n);
--_M_element_count;
return __result;
@@ -1084,64 +1394,65 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
erase(const key_type& __k)
{
typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
- std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
- size_type __result = 0;
-
- _Node** __slot = _M_buckets + __n;
- while (*__slot && !this->_M_compare(__k, __code, *__slot))
- __slot = &((*__slot)->_M_next);
+ std::size_t __bkt = this->_M_bucket_index(__k, __code, _M_bucket_count);
+ // Look for the first matching node with its previous node at the same
+ // time
+ _Node* __n = _M_buckets[__bkt];
+ if (!__n)
+ return 0;
+ _Node* __prev_n = nullptr;
+ if (__bkt != _M_begin_bucket_index)
+ {
+ __prev_n = __n;
+ __n = __n->_M_next;
+ }
+ bool __is_bucket_begin = true;
+ for (;; __prev_n = __n, __n = __n->_M_next)
+ {
+ if (this->_M_compare(__k, __code, __n))
+ break;
+ if (!(__n->_M_next)
+ || this->_M_bucket_index(__n->_M_next, _M_bucket_count) != __bkt)
+ return 0;
+ __is_bucket_begin = false;
+ }
- _Node** __saved_slot = 0;
- while (*__slot && this->_M_compare(__k, __code, *__slot))
+ // We found a matching node, start deallocation loop from it
+ std::size_t __next_bkt = __bkt;
+ _Node* __next_n = __n;
+ size_type __result = 0;
+ _Node* __saved_n = nullptr;
+ do
{
+ _Node* __p = __next_n;
+ __next_n = __p->_M_next;
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 526. Is it undefined if a function in the standard changes
// in parameters?
- if (std::__addressof(this->_M_extract((*__slot)->_M_v))
+ if (std::__addressof(this->_M_extract(__p->_M_v))
!= std::__addressof(__k))
- {
- _Node* __p = *__slot;
- *__slot = __p->_M_next;
- _M_deallocate_node(__p);
- --_M_element_count;
- ++__result;
- }
+ _M_deallocate_node(__p);
else
- {
- __saved_slot = __slot;
- __slot = &((*__slot)->_M_next);
- }
- }
-
- if (__saved_slot)
- {
- _Node* __p = *__saved_slot;
- *__saved_slot = __p->_M_next;
- _M_deallocate_node(__p);
+ __saved_n = __p;
--_M_element_count;
++__result;
+ if (!__next_n)
+ break;
+ __next_bkt = this->_M_bucket_index(__next_n, _M_bucket_count);
}
-
- // If the entire bucket indexed by _M_begin_bucket_index has been
- // erased look forward for the first non-empty bucket.
- if (!_M_buckets[_M_begin_bucket_index])
- {
- if (!_M_element_count)
- _M_begin_bucket_index = _M_bucket_count;
- else
- {
- ++_M_begin_bucket_index;
- while (!_M_buckets[_M_begin_bucket_index])
- ++_M_begin_bucket_index;
- }
- }
-
+ while (__next_bkt == __bkt && this->_M_compare(__k, __code, __next_n));
+
+ if (__saved_n)
+ _M_deallocate_node(__saved_n);
+ if (__is_bucket_begin)
+ _M_remove_bucket_begin(__bkt, __next_n, __next_bkt);
+ else if (__next_n && __next_bkt != __bkt)
+ _M_buckets[__next_bkt] = __prev_n;
+ if (__prev_n)
+ __prev_n->_M_next = __next_n;
return __result;
}
- // ??? This could be optimized by taking advantage of the bucket
- // structure, but it's not clear that it's worth doing. It probably
- // wouldn't even be an optimization unless the load factor is large.
template<typename _Key, typename _Value,
typename _Allocator, typename _ExtractKey, typename _Equal,
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
@@ -1153,9 +1464,42 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
erase(const_iterator __first, const_iterator __last)
{
- while (__first != __last)
- __first = this->erase(__first);
- return iterator(__last._M_cur_node, __last._M_cur_bucket);
+ _Node* __n = __first._M_cur;
+ _Node* __last_n = __last._M_cur;
+ if (__n == __last_n)
+ return iterator(__n);
+
+ std::size_t __bkt = this->_M_bucket_index(__n, _M_bucket_count);
+
+ _Node* __prev_n = _M_get_previous_node(__bkt, __n);
+ bool __is_bucket_begin = __n == _M_bucket_begin(__bkt);
+ std::size_t __n_bkt = __bkt;
+ for (;;)
+ {
+ do
+ {
+ _Node* __tmp = __n;
+ __n = __n->_M_next;
+ _M_deallocate_node(__tmp);
+ --_M_element_count;
+ if (!__n)
+ break;
+ __n_bkt = this->_M_bucket_index(__n, _M_bucket_count);
+ }
+ while (__n != __last_n && __n_bkt == __bkt);
+ if (__is_bucket_begin)
+ _M_remove_bucket_begin(__bkt, __n, __n_bkt);
+ if (__n == __last_n)
+ break;
+ __is_bucket_begin = true;
+ __bkt = __n_bkt;
+ }
+
+ if (__n && __n_bkt != __bkt)
+ _M_buckets[__n_bkt] = __prev_n;
+ if (__prev_n)
+ __prev_n->_M_next = __n;
+ return iterator(__n);
}
template<typename _Key, typename _Value,
@@ -1167,7 +1511,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
clear() noexcept
{
- _M_deallocate_nodes(_M_buckets, _M_bucket_count);
+ _M_deallocate_nodes(_M_buckets[_M_begin_bucket_index]);
+ __builtin_memset(_M_buckets, 0, _M_bucket_count * sizeof(_Bucket));
_M_element_count = 0;
_M_begin_bucket_index = _M_bucket_count;
}
@@ -1181,11 +1526,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
rehash(size_type __n)
{
- const size_type __saved_next_resize = _M_rehash_policy._M_next_resize;
+ const _RehashPolicyState& __saved_state = _M_rehash_policy._M_state();
_M_rehash(std::max(_M_rehash_policy._M_next_bkt(__n),
_M_rehash_policy._M_bkt_for_elements(_M_element_count
+ 1)),
- __saved_next_resize);
+ __saved_state);
}
template<typename _Key, typename _Value,
@@ -1195,46 +1540,75 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
- _M_rehash(size_type __n, size_type __next_resize)
+ _M_rehash(size_type __n, const _RehashPolicyState& __state)
{
- _Node** __new_array = 0;
+ _Bucket* __new_buckets = nullptr;
+ _Node* __p = _M_buckets[_M_begin_bucket_index];
__try
{
- __new_array = _M_allocate_buckets(__n);
+ __new_buckets = _M_allocate_buckets(__n);
+ // First loop to store each node in its new bucket
+ while (__p)
+ {
+ _Node* __next = __p->_M_next;
+ std::size_t __new_index = this->_M_bucket_index(__p, __n);
+ if (!__new_buckets[__new_index])
+ // Store temporarily bucket end node in _M_buckets if possible.
+ // This will boost second loop where we need to access bucket
+ // end node quickly.
+ if (__new_index < _M_bucket_count)
+ _M_buckets[__new_index] = __p;
+ __p->_M_next = __new_buckets[__new_index];
+ __new_buckets[__new_index] = __p;
+ __p = __next;
+ }
_M_begin_bucket_index = __n;
- for (size_type __i = 0; __i < _M_bucket_count; ++__i)
- while (_Node* __p = _M_buckets[__i])
+ _Node* __prev_node = nullptr;
+ // Second loop to link all nodes together and to fix bucket values so
+ // that they contain the before begin node of the bucket.
+ for (size_type __i = 0; __i != __n; ++__i)
+ if (__new_buckets[__i])
{
- std::size_t __new_index = this->_M_bucket_index(__p, __n);
- _M_buckets[__i] = __p->_M_next;
- __p->_M_next = __new_array[__new_index];
- __new_array[__new_index] = __p;
- if (__new_index < _M_begin_bucket_index)
- _M_begin_bucket_index = __new_index;
+ if (__prev_node)
+ {
+ __prev_node->_M_next = __new_buckets[__i];
+ __new_buckets[__i] = __prev_node;
+ }
+ else
+ _M_begin_bucket_index = __i;
+ if (__i < _M_bucket_count)
+ __prev_node = _M_buckets[__i];
+ else
+ {
+ __prev_node = __new_buckets[__i];
+ while (__prev_node->_M_next)
+ __prev_node = __prev_node->_M_next;
+ }
}
_M_deallocate_buckets(_M_buckets, _M_bucket_count);
_M_bucket_count = __n;
- _M_buckets = __new_array;
+ _M_buckets = __new_buckets;
}
__catch(...)
{
- if (__new_array)
+ if (__new_buckets)
{
// A failure here means that a hash function threw an exception.
// We can't restore the previous state without calling the hash
// function again, so the only sensible recovery is to delete
// everything.
- _M_deallocate_nodes(__new_array, __n);
- _M_deallocate_buckets(__new_array, __n);
- _M_deallocate_nodes(_M_buckets, _M_bucket_count);
+ _M_deallocate_nodes(__new_buckets, __n);
+ _M_deallocate_buckets(__new_buckets, __n);
+ _M_deallocate_nodes(__p);
+ __builtin_memset(_M_buckets, 0, sizeof(_Bucket) * _M_bucket_count);
_M_element_count = 0;
_M_begin_bucket_index = _M_bucket_count;
- _M_rehash_policy._M_next_resize = 0;
+ _M_rehash_policy._M_reset(_RehashPolicyState());
}
else
// A failure here means that buckets allocation failed. We only
// have to restore hash policy previous state.
- _M_rehash_policy._M_next_resize = __next_resize;
+ _M_rehash_policy._M_reset(__state);
__throw_exception_again;
}
}
diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h
index acb7e99a8df..44c749af515 100644
--- a/libstdc++-v3/include/bits/hashtable_policy.h
+++ b/libstdc++-v3/include/bits/hashtable_policy.h
@@ -59,6 +59,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __distance_fw(__first, __last, _Tag());
}
+ // Helper type used to detect when the hash functor is noexcept qualified or
+ // not
+ template <typename _Key, typename _Hash>
+ struct __is_noexcept_hash : std::integral_constant<bool,
+ noexcept(declval<const _Hash&>()(declval<const _Key&>()))>
+ {};
+
// Auxiliary types used for all instantiations of _Hashtable: nodes
// and iterators.
@@ -211,155 +218,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
};
- template<typename _Value, bool __cache>
- struct _Hashtable_iterator_base
- {
- _Hashtable_iterator_base(_Hash_node<_Value, __cache>* __node,
- _Hash_node<_Value, __cache>** __bucket)
- : _M_cur_node(__node), _M_cur_bucket(__bucket) { }
-
- void
- _M_incr()
- {
- _M_cur_node = _M_cur_node->_M_next;
- if (!_M_cur_node)
- _M_incr_bucket();
- }
-
- void
- _M_incr_bucket();
-
- _Hash_node<_Value, __cache>* _M_cur_node;
- _Hash_node<_Value, __cache>** _M_cur_bucket;
- };
-
- // Global iterators, used for arbitrary iteration within a hash
- // table. Larger and more expensive than local iterators.
- template<typename _Value, bool __cache>
- void
- _Hashtable_iterator_base<_Value, __cache>::
- _M_incr_bucket()
- {
- ++_M_cur_bucket;
-
- // This loop requires the bucket array to have a non-null sentinel.
- while (!*_M_cur_bucket)
- ++_M_cur_bucket;
- _M_cur_node = *_M_cur_bucket;
- }
-
- template<typename _Value, bool __cache>
- inline bool
- operator==(const _Hashtable_iterator_base<_Value, __cache>& __x,
- const _Hashtable_iterator_base<_Value, __cache>& __y)
- { return __x._M_cur_node == __y._M_cur_node; }
-
- template<typename _Value, bool __cache>
- inline bool
- operator!=(const _Hashtable_iterator_base<_Value, __cache>& __x,
- const _Hashtable_iterator_base<_Value, __cache>& __y)
- { return __x._M_cur_node != __y._M_cur_node; }
-
- template<typename _Value, bool __constant_iterators, bool __cache>
- struct _Hashtable_iterator
- : public _Hashtable_iterator_base<_Value, __cache>
- {
- typedef _Value value_type;
- typedef typename std::conditional<__constant_iterators,
- const _Value*, _Value*>::type
- pointer;
- typedef typename std::conditional<__constant_iterators,
- const _Value&, _Value&>::type
- reference;
- typedef std::ptrdiff_t difference_type;
- typedef std::forward_iterator_tag iterator_category;
-
- _Hashtable_iterator()
- : _Hashtable_iterator_base<_Value, __cache>(0, 0) { }
-
- _Hashtable_iterator(_Hash_node<_Value, __cache>* __p,
- _Hash_node<_Value, __cache>** __b)
- : _Hashtable_iterator_base<_Value, __cache>(__p, __b) { }
-
- explicit
- _Hashtable_iterator(_Hash_node<_Value, __cache>** __b)
- : _Hashtable_iterator_base<_Value, __cache>(*__b, __b) { }
-
- reference
- operator*() const
- { return this->_M_cur_node->_M_v; }
-
- pointer
- operator->() const
- { return std::__addressof(this->_M_cur_node->_M_v); }
-
- _Hashtable_iterator&
- operator++()
- {
- this->_M_incr();
- return *this;
- }
-
- _Hashtable_iterator
- operator++(int)
- {
- _Hashtable_iterator __tmp(*this);
- this->_M_incr();
- return __tmp;
- }
- };
-
- template<typename _Value, bool __constant_iterators, bool __cache>
- struct _Hashtable_const_iterator
- : public _Hashtable_iterator_base<_Value, __cache>
- {
- typedef _Value value_type;
- typedef const _Value* pointer;
- typedef const _Value& reference;
- typedef std::ptrdiff_t difference_type;
- typedef std::forward_iterator_tag iterator_category;
-
- _Hashtable_const_iterator()
- : _Hashtable_iterator_base<_Value, __cache>(0, 0) { }
-
- _Hashtable_const_iterator(_Hash_node<_Value, __cache>* __p,
- _Hash_node<_Value, __cache>** __b)
- : _Hashtable_iterator_base<_Value, __cache>(__p, __b) { }
-
- explicit
- _Hashtable_const_iterator(_Hash_node<_Value, __cache>** __b)
- : _Hashtable_iterator_base<_Value, __cache>(*__b, __b) { }
-
- _Hashtable_const_iterator(const _Hashtable_iterator<_Value,
- __constant_iterators, __cache>& __x)
- : _Hashtable_iterator_base<_Value, __cache>(__x._M_cur_node,
- __x._M_cur_bucket) { }
-
- reference
- operator*() const
- { return this->_M_cur_node->_M_v; }
-
- pointer
- operator->() const
- { return std::__addressof(this->_M_cur_node->_M_v); }
-
- _Hashtable_const_iterator&
- operator++()
- {
- this->_M_incr();
- return *this;
- }
-
- _Hashtable_const_iterator
- operator++(int)
- {
- _Hashtable_const_iterator __tmp(*this);
- this->_M_incr();
- return __tmp;
- }
- };
-
-
// Many of class template _Hashtable's template parameters are policy
// classes. These are defaults for the policies.
@@ -388,7 +246,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct _Prime_rehash_policy
{
_Prime_rehash_policy(float __z = 1.0)
- : _M_max_load_factor(__z), _M_growth_factor(2.f), _M_next_resize(0) { }
+ : _M_max_load_factor(__z), _M_prev_resize(0), _M_next_resize(0) { }
float
max_load_factor() const noexcept
@@ -410,10 +268,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt,
std::size_t __n_ins) const;
+ typedef std::pair<std::size_t, std::size_t> _State;
+
+ _State
+ _M_state() const
+ { return std::make_pair(_M_prev_resize, _M_next_resize); }
+
+ void
+ _M_reset(const _State& __state)
+ {
+ _M_prev_resize = __state.first;
+ _M_next_resize = __state.second;
+ }
+
enum { _S_n_primes = sizeof(unsigned long) != 8 ? 256 : 256 + 48 };
float _M_max_load_factor;
- float _M_growth_factor;
+ mutable std::size_t _M_prev_resize;
mutable std::size_t _M_next_resize;
};
@@ -429,15 +300,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
// Optimize lookups involving the first elements of __prime_list.
// (useful to speed-up, eg, constructors)
- static const unsigned char __fast_bkt[12]
+ static const unsigned long __fast_bkt[12]
= { 2, 2, 2, 3, 5, 5, 7, 7, 11, 11, 11, 11 };
- const unsigned long __p
- = __n <= 11 ? __fast_bkt[__n]
- : *std::lower_bound(__prime_list + 5,
- __prime_list + _S_n_primes, __n);
- _M_next_resize = __builtin_floor(__p * (long double)_M_max_load_factor);
- return __p;
+ const unsigned long* __p
+ = __n <= 11 ? __fast_bkt + __n
+ : std::lower_bound(__prime_list + 5,
+ __prime_list + _S_n_primes, __n);
+
+ _M_prev_resize = __builtin_floor(*__p * (long double)_M_max_load_factor);
+ if (__p != __fast_bkt)
+ _M_prev_resize = std::min(_M_prev_resize,
+ static_cast<std::size_t>(*(__p - 1)));
+ // Lets guaranty a minimal grow step of 11:
+ if (*__p - __n < 11)
+ __p = std::lower_bound(__prime_list + 5,
+ __prime_list + _S_n_primes, __n + 11);
+ _M_next_resize = __builtin_floor(*__p * (long double)_M_max_load_factor);
+ return *__p;
}
// Return the smallest prime p such that alpha p >= n, where alpha
@@ -461,17 +341,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt,
std::size_t __n_ins) const
{
- if (__n_elt + __n_ins > _M_next_resize)
+ if (__n_elt + __n_ins >= _M_next_resize)
{
- long double __min_bkts = ((__n_elt + __n_ins)
- / (long double)_M_max_load_factor);
- if (__min_bkts > __n_bkt)
- {
- __min_bkts = std::max(__min_bkts, (long double)_M_growth_factor
- * __n_bkt);
- return std::make_pair(true,
- _M_next_bkt(__builtin_ceil(__min_bkts)));
- }
+ long double __min_bkts = (__n_elt + __n_ins)
+ / (long double)_M_max_load_factor;
+ if (__min_bkts >= __n_bkt)
+ return std::make_pair(true,
+ _M_next_bkt(__builtin_floor(__min_bkts) + 1));
else
{
_M_next_resize
@@ -479,6 +355,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return std::make_pair(false, 0);
}
}
+ else if (__n_elt + __n_ins < _M_prev_resize)
+ {
+ long double __min_bkts = (__n_elt + __n_ins)
+ / (long double)_M_max_load_factor;
+ return std::make_pair(true,
+ _M_next_bkt(__builtin_floor(__min_bkts) + 1));
+ }
else
return std::make_pair(false, 0);
}
@@ -538,8 +421,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::size_t __n = __h->_M_bucket_index(__k, __code,
__h->_M_bucket_count);
- typename _Hashtable::_Node* __p =
- __h->_M_find_node(__h->_M_buckets[__n], __k, __code);
+ typename _Hashtable::_Node* __p = __h->_M_find_node(__n, __k, __code);
if (!__p)
return __h->_M_insert_bucket(std::make_pair(__k, mapped_type()),
__n, __code)->second;
@@ -557,8 +439,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::size_t __n = __h->_M_bucket_index(__k, __code,
__h->_M_bucket_count);
- typename _Hashtable::_Node* __p =
- __h->_M_find_node(__h->_M_buckets[__n], __k, __code);
+ typename _Hashtable::_Node* __p = __h->_M_find_node(__n, __k, __code);
if (!__p)
return __h->_M_insert_bucket(std::make_pair(std::move(__k),
mapped_type()),
@@ -577,8 +458,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::size_t __n = __h->_M_bucket_index(__k, __code,
__h->_M_bucket_count);
- typename _Hashtable::_Node* __p =
- __h->_M_find_node(__h->_M_buckets[__n], __k, __code);
+ typename _Hashtable::_Node* __p = __h->_M_find_node(__n, __k, __code);
if (!__p)
__throw_out_of_range(__N("_Map_base::at"));
return (__p->_M_v).second;
@@ -595,8 +475,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::size_t __n = __h->_M_bucket_index(__k, __code,
__h->_M_bucket_count);
- typename _Hashtable::_Node* __p =
- __h->_M_find_node(__h->_M_buckets[__n], __k, __code);
+ typename _Hashtable::_Node* __p = __h->_M_find_node(__n, __k, __code);
if (!__p)
__throw_out_of_range(__N("_Map_base::at"));
return (__p->_M_v).second;
diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h
index 32addf95105..33128dd4ed6 100644
--- a/libstdc++-v3/include/bits/shared_ptr.h
+++ b/libstdc++-v3/include/bits/shared_ptr.h
@@ -619,7 +619,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __hash_base<size_t, shared_ptr<_Tp>>
{
size_t
- operator()(const shared_ptr<_Tp>& __s) const
+ operator()(const shared_ptr<_Tp>& __s) const noexcept
{ return std::hash<_Tp*>()(__s.get()); }
};
diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h
index fbbadd1aaaa..c0677547553 100644
--- a/libstdc++-v3/include/bits/shared_ptr_base.h
+++ b/libstdc++-v3/include/bits/shared_ptr_base.h
@@ -1450,7 +1450,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __hash_base<size_t, __shared_ptr<_Tp, _Lp>>
{
size_t
- operator()(const __shared_ptr<_Tp, _Lp>& __s) const
+ operator()(const __shared_ptr<_Tp, _Lp>& __s) const noexcept
{ return std::hash<_Tp*>()(__s.get()); }
};
diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h
index 8f286400aec..bec63ff03f9 100644
--- a/libstdc++-v3/include/bits/stl_bvector.h
+++ b/libstdc++-v3/include/bits/stl_bvector.h
@@ -1075,7 +1075,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __hash_base<size_t, _GLIBCXX_STD_C::vector<bool, _Alloc>>
{
size_t
- operator()(const _GLIBCXX_STD_C::vector<bool, _Alloc>& __b) const;
+ operator()(const _GLIBCXX_STD_C::vector<bool, _Alloc>&) const noexcept;
};
_GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h
index 45824f04079..f1c4cfefa57 100644
--- a/libstdc++-v3/include/bits/stl_map.h
+++ b/libstdc++-v3/include/bits/stl_map.h
@@ -617,6 +617,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
iterator
erase(const_iterator __position)
{ return _M_t.erase(__position); }
+
+ // LWG 2059.
+ iterator
+ erase(iterator __position)
+ { return _M_t.erase(__position); }
#else
/**
* @brief Erases an element from a %map.
diff --git a/libstdc++-v3/include/bits/stl_multimap.h b/libstdc++-v3/include/bits/stl_multimap.h
index fd5a5a8cffb..ae4389e2709 100644
--- a/libstdc++-v3/include/bits/stl_multimap.h
+++ b/libstdc++-v3/include/bits/stl_multimap.h
@@ -536,6 +536,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
iterator
erase(const_iterator __position)
{ return _M_t.erase(__position); }
+
+ // LWG 2059.
+ iterator
+ erase(iterator __position)
+ { return _M_t.erase(__position); }
#else
/**
* @brief Erases an element from a %multimap.
diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h
index 8c5f0c30a0f..ee56bbc7525 100644
--- a/libstdc++-v3/include/bits/stl_tree.h
+++ b/libstdc++-v3/include/bits/stl_tree.h
@@ -767,6 +767,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_erase_aux(__position);
return __result._M_const_cast();
}
+
+ // LWG 2059.
+ iterator
+ erase(iterator __position)
+ {
+ iterator __result = __position;
+ ++__result;
+ _M_erase_aux(__position);
+ return __result;
+ }
#else
void
erase(iterator __position)
diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h
index 869d931330c..0a127996e52 100644
--- a/libstdc++-v3/include/bits/unique_ptr.h
+++ b/libstdc++-v3/include/bits/unique_ptr.h
@@ -545,7 +545,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __hash_base<size_t, unique_ptr<_Tp, _Dp>>
{
size_t
- operator()(const unique_ptr<_Tp, _Dp>& __u) const
+ operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept
{
typedef unique_ptr<_Tp, _Dp> _UP;
return std::hash<typename _UP::pointer>()(__u.get());
diff --git a/libstdc++-v3/include/bits/unordered_map.h b/libstdc++-v3/include/bits/unordered_map.h
index c77bab12fba..7c810d3801f 100644
--- a/libstdc++-v3/include/bits/unordered_map.h
+++ b/libstdc++-v3/include/bits/unordered_map.h
@@ -40,7 +40,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
class _Hash = hash<_Key>,
class _Pred = std::equal_to<_Key>,
class _Alloc = std::allocator<std::pair<const _Key, _Tp> >,
- bool __cache_hash_code = false>
+ bool __cache_hash_code =
+ __not_<__and_<is_integral<_Key>,
+ __detail::__is_noexcept_hash<_Key, _Hash>>>::value>
class __unordered_map
: public _Hashtable<_Key, std::pair<const _Key, _Tp>, _Alloc,
std::_Select1st<std::pair<const _Key, _Tp> >, _Pred,
@@ -109,7 +111,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
class _Hash = hash<_Key>,
class _Pred = std::equal_to<_Key>,
class _Alloc = std::allocator<std::pair<const _Key, _Tp> >,
- bool __cache_hash_code = false>
+ bool __cache_hash_code =
+ __not_<__and_<is_integral<_Key>,
+ __detail::__is_noexcept_hash<_Key, _Hash>>>::value>
class __unordered_multimap
: public _Hashtable<_Key, std::pair<const _Key, _Tp>,
_Alloc,
diff --git a/libstdc++-v3/include/bits/unordered_set.h b/libstdc++-v3/include/bits/unordered_set.h
index 12b7bda138f..9aef0829749 100644
--- a/libstdc++-v3/include/bits/unordered_set.h
+++ b/libstdc++-v3/include/bits/unordered_set.h
@@ -40,7 +40,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
class _Hash = hash<_Value>,
class _Pred = std::equal_to<_Value>,
class _Alloc = std::allocator<_Value>,
- bool __cache_hash_code = false>
+ bool __cache_hash_code =
+ __not_<__and_<is_integral<_Value>,
+ __detail::__is_noexcept_hash<_Value, _Hash>>>::value>
class __unordered_set
: public _Hashtable<_Value, _Value, _Alloc,
std::_Identity<_Value>, _Pred,
@@ -121,7 +123,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
class _Hash = hash<_Value>,
class _Pred = std::equal_to<_Value>,
class _Alloc = std::allocator<_Value>,
- bool __cache_hash_code = false>
+ bool __cache_hash_code =
+ __not_<__and_<is_integral<_Value>,
+ __detail::__is_noexcept_hash<_Value, _Hash>>>::value>
class __unordered_multiset
: public _Hashtable<_Value, _Value, _Alloc,
std::_Identity<_Value>, _Pred,
diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc
index b74684228c1..d9c3b659e6b 100644
--- a/libstdc++-v3/include/bits/vector.tcc
+++ b/libstdc++-v3/include/bits/vector.tcc
@@ -818,7 +818,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Alloc>
size_t
hash<_GLIBCXX_STD_C::vector<bool, _Alloc>>::
- operator()(const _GLIBCXX_STD_C::vector<bool, _Alloc>& __b) const
+ operator()(const _GLIBCXX_STD_C::vector<bool, _Alloc>& __b) const noexcept
{
size_t __hash = 0;
using _GLIBCXX_STD_C::_S_word_bit;
diff --git a/libstdc++-v3/include/debug/bitset b/libstdc++-v3/include/debug/bitset
index 21d281787ad..3d865c1c1c2 100644
--- a/libstdc++-v3/include/debug/bitset
+++ b/libstdc++-v3/include/debug/bitset
@@ -51,7 +51,7 @@ namespace __debug
public:
// In C++0x we rely on normal reference type to preserve the property
// of bitset to be use as a literal.
- // TODO: Find an other solution.
+ // TODO: Find another solution.
#ifdef __GXX_EXPERIMENTAL_CXX0X__
typedef typename _Base::reference reference;
#else
@@ -272,11 +272,14 @@ namespace __debug
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 11. Bitset minor problems
- bool
+ _GLIBCXX_CONSTEXPR bool
operator[](size_t __pos) const
{
+#ifndef __GXX_EXPERIMENTAL_CXX0X__
+ // TODO: Check in debug-mode too.
__glibcxx_check_subscript(__pos);
- return _M_base()[__pos];
+#endif
+ return _Base::operator[](__pos);
}
using _Base::to_ulong;
@@ -414,7 +417,7 @@ namespace __debug
: public __hash_base<size_t, __debug::bitset<_Nb>>
{
size_t
- operator()(const __debug::bitset<_Nb>& __b) const
+ operator()(const __debug::bitset<_Nb>& __b) const noexcept
{ return std::hash<_GLIBCXX_STD_C::bitset<_Nb>>()(__b._M_base()); }
};
#endif
diff --git a/libstdc++-v3/include/debug/map.h b/libstdc++-v3/include/debug/map.h
index e80c1e3b4b7..9abfee867d0 100644
--- a/libstdc++-v3/include/debug/map.h
+++ b/libstdc++-v3/include/debug/map.h
@@ -271,6 +271,10 @@ namespace __debug
this->_M_invalidate_if(_Equal(__position.base()));
return iterator(_Base::erase(__position.base()), this);
}
+
+ iterator
+ erase(iterator __position)
+ { return erase(const_iterator(__position)); }
#else
void
erase(iterator __position)
diff --git a/libstdc++-v3/include/debug/multimap.h b/libstdc++-v3/include/debug/multimap.h
index cf18d7cc114..e43094f8b4d 100644
--- a/libstdc++-v3/include/debug/multimap.h
+++ b/libstdc++-v3/include/debug/multimap.h
@@ -254,6 +254,10 @@ namespace __debug
this->_M_invalidate_if(_Equal(__position.base()));
return iterator(_Base::erase(__position.base()), this);
}
+
+ iterator
+ erase(iterator __position)
+ { return erase(const_iterator(__position)); }
#else
void
erase(iterator __position)
diff --git a/libstdc++-v3/include/debug/unordered_map b/libstdc++-v3/include/debug/unordered_map
index 6eeff6429e4..6ad46b627d3 100644
--- a/libstdc++-v3/include/debug/unordered_map
+++ b/libstdc++-v3/include/debug/unordered_map
@@ -334,6 +334,10 @@ namespace __debug
}
iterator
+ erase(iterator __it)
+ { return erase(const_iterator(__it)); }
+
+ iterator
erase(const_iterator __first, const_iterator __last)
{
__glibcxx_check_erase_range(__first, __last);
@@ -391,11 +395,11 @@ namespace __debug
static _Base_local_iterator
_S_to_local(_Base_iterator __it)
- { return _Base_local_iterator(__it._M_cur_node); }
+ { return _Base_local_iterator(__it._M_cur); }
static _Base_const_local_iterator
_S_to_local(_Base_const_iterator __it)
- { return _Base_const_local_iterator(__it._M_cur_node); }
+ { return _Base_const_local_iterator(__it._M_cur); }
};
template<typename _Key, typename _Tp, typename _Hash,
@@ -709,6 +713,10 @@ namespace __debug
}
iterator
+ erase(iterator __it)
+ { return erase(const_iterator(__it)); }
+
+ iterator
erase(const_iterator __first, const_iterator __last)
{
__glibcxx_check_erase_range(__first, __last);
@@ -766,11 +774,11 @@ namespace __debug
static _Base_local_iterator
_S_to_local(_Base_iterator __it)
- { return _Base_local_iterator(__it._M_cur_node); }
+ { return _Base_local_iterator(__it._M_cur); }
static _Base_const_local_iterator
_S_to_local(_Base_const_iterator __it)
- { return _Base_const_local_iterator(__it._M_cur_node); }
+ { return _Base_const_local_iterator(__it._M_cur); }
};
template<typename _Key, typename _Tp, typename _Hash,
diff --git a/libstdc++-v3/include/debug/unordered_set b/libstdc++-v3/include/debug/unordered_set
index 0cc3a12cf37..2f41bc3a25d 100644
--- a/libstdc++-v3/include/debug/unordered_set
+++ b/libstdc++-v3/include/debug/unordered_set
@@ -330,6 +330,10 @@ namespace __debug
}
iterator
+ erase(iterator __it)
+ { return erase(const_iterator(__it)); }
+
+ iterator
erase(const_iterator __first, const_iterator __last)
{
__glibcxx_check_erase_range(__first, __last);
@@ -390,11 +394,11 @@ namespace __debug
static _Base_local_iterator
_S_to_local(_Base_iterator __it)
- { return _Base_local_iterator(__it._M_cur_node); }
+ { return _Base_local_iterator(__it._M_cur); }
static _Base_const_local_iterator
_S_to_local(_Base_const_iterator __it)
- { return _Base_const_local_iterator(__it._M_cur_node); }
+ { return _Base_const_local_iterator(__it._M_cur); }
};
template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
@@ -696,6 +700,10 @@ namespace __debug
}
iterator
+ erase(iterator __it)
+ { return erase(const_iterator(__it)); }
+
+ iterator
erase(const_iterator __first, const_iterator __last)
{
__glibcxx_check_erase_range(__first, __last);
@@ -751,11 +759,11 @@ namespace __debug
static _Base_local_iterator
_S_to_local(_Base_iterator __it)
- { return _Base_local_iterator(__it._M_cur_node); }
+ { return _Base_local_iterator(__it._M_cur); }
static _Base_const_local_iterator
_S_to_local(_Base_const_iterator __it)
- { return _Base_const_local_iterator(__it._M_cur_node); }
+ { return _Base_const_local_iterator(__it._M_cur); }
};
template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector
index 82662b44605..5ee0fabc32a 100644
--- a/libstdc++-v3/include/debug/vector
+++ b/libstdc++-v3/include/debug/vector
@@ -625,7 +625,7 @@ namespace __debug
: public __hash_base<size_t, __debug::vector<bool, _Alloc>>
{
size_t
- operator()(const __debug::vector<bool, _Alloc>& __b) const
+ operator()(const __debug::vector<bool, _Alloc>& __b) const noexcept
{ return std::hash<_GLIBCXX_STD_C::vector<bool, _Alloc>>()
(__b._M_base()); }
};
diff --git a/libstdc++-v3/include/ext/vstring.h b/libstdc++-v3/include/ext/vstring.h
index a613e364d3a..8c4120a3be2 100644
--- a/libstdc++-v3/include/ext/vstring.h
+++ b/libstdc++-v3/include/ext/vstring.h
@@ -2769,7 +2769,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __hash_base<size_t, __gnu_cxx::__vstring>
{
size_t
- operator()(const __gnu_cxx::__vstring& __s) const
+ operator()(const __gnu_cxx::__vstring& __s) const noexcept
{ return std::_Hash_impl::hash(__s.data(), __s.length()); }
};
@@ -2780,7 +2780,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __hash_base<size_t, __gnu_cxx::__wvstring>
{
size_t
- operator()(const __gnu_cxx::__wvstring& __s) const
+ operator()(const __gnu_cxx::__wvstring& __s) const noexcept
{ return std::_Hash_impl::hash(__s.data(),
__s.length() * sizeof(wchar_t)); }
};
@@ -2793,7 +2793,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __hash_base<size_t, __gnu_cxx::__u16vstring>
{
size_t
- operator()(const __gnu_cxx::__u16vstring& __s) const
+ operator()(const __gnu_cxx::__u16vstring& __s) const noexcept
{ return std::_Hash_impl::hash(__s.data(),
__s.length() * sizeof(char16_t)); }
};
@@ -2804,7 +2804,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __hash_base<size_t, __gnu_cxx::__u32vstring>
{
size_t
- operator()(const __gnu_cxx::__u32vstring& __s) const
+ operator()(const __gnu_cxx::__u32vstring& __s) const noexcept
{ return std::_Hash_impl::hash(__s.data(),
__s.length() * sizeof(char32_t)); }
};
diff --git a/libstdc++-v3/include/profile/bitset b/libstdc++-v3/include/profile/bitset
index bd4aa3e152f..17ee49b5a60 100644
--- a/libstdc++-v3/include/profile/bitset
+++ b/libstdc++-v3/include/profile/bitset
@@ -232,10 +232,10 @@ namespace __profile
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 11. Bitset minor problems
- bool
+ _GLIBCXX_CONSTEXPR bool
operator[](size_t __pos) const
{
- return _M_base()[__pos];
+ return _Base::operator[](__pos);
}
using _Base::to_ulong;
@@ -372,7 +372,7 @@ namespace __profile
: public __hash_base<size_t, __profile::bitset<_Nb>>
{
size_t
- operator()(const __profile::bitset<_Nb>& __b) const
+ operator()(const __profile::bitset<_Nb>& __b) const noexcept
{ return std::hash<_GLIBCXX_STD_C::bitset<_Nb>>()(__b._M_base()); }
};
#endif
diff --git a/libstdc++-v3/include/profile/map.h b/libstdc++-v3/include/profile/map.h
index 622bc575ad2..eb5c5d90d9c 100644
--- a/libstdc++-v3/include/profile/map.h
+++ b/libstdc++-v3/include/profile/map.h
@@ -327,6 +327,10 @@ namespace __profile
__profcxx_map_to_unordered_map_erase(this, size(), 1);
return __i;
}
+
+ iterator
+ erase(iterator __position)
+ { return erase(const_iterator(__position)); }
#else
void
erase(iterator __position)
diff --git a/libstdc++-v3/include/profile/multimap.h b/libstdc++-v3/include/profile/multimap.h
index 547a221b330..b71be4570bd 100644
--- a/libstdc++-v3/include/profile/multimap.h
+++ b/libstdc++-v3/include/profile/multimap.h
@@ -226,6 +226,10 @@ namespace __profile
iterator
erase(const_iterator __position)
{ return iterator(_Base::erase(__position)); }
+
+ iterator
+ erase(iterator __position)
+ { return iterator(_Base::erase(__position)); }
#else
void
erase(iterator __position)
diff --git a/libstdc++-v3/include/profile/vector b/libstdc++-v3/include/profile/vector
index 86aefd649e3..0526c5aabb7 100644
--- a/libstdc++-v3/include/profile/vector
+++ b/libstdc++-v3/include/profile/vector
@@ -529,7 +529,7 @@ namespace __profile
: public __hash_base<size_t, __profile::vector<bool, _Alloc>>
{
size_t
- operator()(const __profile::vector<bool, _Alloc>& __b) const
+ operator()(const __profile::vector<bool, _Alloc>& __b) const noexcept
{ return std::hash<_GLIBCXX_STD_C::vector<bool, _Alloc>>()
(__b._M_base()); }
};
diff --git a/libstdc++-v3/include/std/bitset b/libstdc++-v3/include/std/bitset
index 813ed4b2599..e07c5e08970 100644
--- a/libstdc++-v3/include/std/bitset
+++ b/libstdc++-v3/include/std/bitset
@@ -1555,7 +1555,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __hash_base<size_t, _GLIBCXX_STD_C::bitset<_Nb>>
{
size_t
- operator()(const _GLIBCXX_STD_C::bitset<_Nb>& __b) const
+ operator()(const _GLIBCXX_STD_C::bitset<_Nb>& __b) const noexcept
{
const size_t __clength = (_Nb + __CHAR_BIT__ - 1) / __CHAR_BIT__;
return std::_Hash_impl::hash(__b._M_getdata(), __clength);
@@ -1567,7 +1567,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __hash_base<size_t, _GLIBCXX_STD_C::bitset<0>>
{
size_t
- operator()(const _GLIBCXX_STD_C::bitset<0>&) const
+ operator()(const _GLIBCXX_STD_C::bitset<0>&) const noexcept
{ return 0; }
};
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 4a04eca8969..465fc569b23 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -843,22 +843,24 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
: public integral_constant<int, 0>
{ };
- /// The type of placeholder objects defined by libstdc++.
+ /** @brief The type of placeholder objects defined by libstdc++.
+ * @ingroup binders
+ */
template<int _Num> struct _Placeholder { };
_GLIBCXX_END_NAMESPACE_VERSION
/** @namespace std::placeholders
- * @brief ISO C++ 0x entities sub namespace for functional.
+ * @brief ISO C++11 entities sub-namespace for functional.
* @ingroup binders
- *
- * Define a large number of placeholders. There is no way to
- * simplify this with variadic templates, because we're introducing
- * unique names for each.
*/
namespace placeholders
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ /* Define a large number of placeholders. There is no way to
+ * simplify this with variadic templates, because we're introducing
+ * unique names for each.
+ */
extern const _Placeholder<1> _1;
extern const _Placeholder<2> _2;
extern const _Placeholder<3> _3;
@@ -903,6 +905,11 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
: public integral_constant<int, _Num>
{ };
+ template<int _Num>
+ struct is_placeholder<const _Placeholder<_Num> >
+ : public integral_constant<int, _Num>
+ { };
+
/**
* Used by _Safe_tuple_element to indicate that there is no tuple
* element at this position.
@@ -1424,8 +1431,56 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
* @brief Class template _Bind is always a bind expression.
* @ingroup binders
*/
+ template<typename _Signature>
+ struct is_bind_expression<const _Bind<_Signature> >
+ : public true_type { };
+
+ /**
+ * @brief Class template _Bind is always a bind expression.
+ * @ingroup binders
+ */
+ template<typename _Signature>
+ struct is_bind_expression<volatile _Bind<_Signature> >
+ : public true_type { };
+
+ /**
+ * @brief Class template _Bind is always a bind expression.
+ * @ingroup binders
+ */
+ template<typename _Signature>
+ struct is_bind_expression<const volatile _Bind<_Signature>>
+ : public true_type { };
+
+ /**
+ * @brief Class template _Bind_result is always a bind expression.
+ * @ingroup binders
+ */
+ template<typename _Result, typename _Signature>
+ struct is_bind_expression<_Bind_result<_Result, _Signature>>
+ : public true_type { };
+
+ /**
+ * @brief Class template _Bind_result is always a bind expression.
+ * @ingroup binders
+ */
+ template<typename _Result, typename _Signature>
+ struct is_bind_expression<const _Bind_result<_Result, _Signature>>
+ : public true_type { };
+
+ /**
+ * @brief Class template _Bind_result is always a bind expression.
+ * @ingroup binders
+ */
+ template<typename _Result, typename _Signature>
+ struct is_bind_expression<volatile _Bind_result<_Result, _Signature>>
+ : public true_type { };
+
+ /**
+ * @brief Class template _Bind_result is always a bind expression.
+ * @ingroup binders
+ */
template<typename _Result, typename _Signature>
- struct is_bind_expression<_Bind_result<_Result, _Signature> >
+ struct is_bind_expression<const volatile _Bind_result<_Result, _Signature>>
: public true_type { };
// Trait type used to remove std::bind() from overload set via SFINAE
diff --git a/libstdc++-v3/include/std/iomanip b/libstdc++-v3/include/std/iomanip
index ea2c44acf6f..e725b2514df 100644
--- a/libstdc++-v3/include/std/iomanip
+++ b/libstdc++-v3/include/std/iomanip
@@ -1,7 +1,7 @@
// Standard stream manipulators -*- C++ -*-
// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
-// 2006, 2007, 2008, 2009, 2010
+// 2006, 2007, 2008, 2009, 2010, 2011
// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
@@ -262,18 +262,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __is, _Get_money<_MoneyT> __f)
{
- typedef istreambuf_iterator<_CharT, _Traits> _Iter;
- typedef money_get<_CharT, _Iter> _MoneyGet;
-
- ios_base::iostate __err = ios_base::goodbit;
- const _MoneyGet& __mg = use_facet<_MoneyGet>(__is.getloc());
-
- __mg.get(_Iter(__is.rdbuf()), _Iter(), __f._M_intl,
- __is, __err, __f._M_mon);
-
- if (ios_base::goodbit != __err)
- __is.setstate(__err);
-
+ typename basic_istream<_CharT, _Traits>::sentry __cerb(__is, false);
+ if (__cerb)
+ {
+ ios_base::iostate __err = ios_base::goodbit;
+ __try
+ {
+ typedef istreambuf_iterator<_CharT, _Traits> _Iter;
+ typedef money_get<_CharT, _Iter> _MoneyGet;
+
+ const _MoneyGet& __mg = use_facet<_MoneyGet>(__is.getloc());
+ __mg.get(_Iter(__is.rdbuf()), _Iter(), __f._M_intl,
+ __is, __err, __f._M_mon);
+ }
+ __catch(__cxxabiv1::__forced_unwind&)
+ {
+ __is._M_setstate(ios_base::badbit);
+ __throw_exception_again;
+ }
+ __catch(...)
+ { __is._M_setstate(ios_base::badbit); }
+ if (ios_base::goodbit != __err)
+ __is.setstate(__err);
+ }
return __is;
}
@@ -298,16 +309,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os, _Put_money<_MoneyT> __f)
{
- typedef ostreambuf_iterator<_CharT, _Traits> _Iter;
- typedef money_put<_CharT, _Iter> _MoneyPut;
-
- const _MoneyPut& __mp = use_facet<_MoneyPut>(__os.getloc());
- const _Iter __end = __mp.put(_Iter(__os.rdbuf()), __f._M_intl,
- __os, __os.fill(), __f._M_mon);
-
- if (__end.failed())
- __os.setstate(ios_base::badbit);
-
+ typename basic_ostream<_CharT, _Traits>::sentry __cerb(__os);
+ if (__cerb)
+ {
+ __try
+ {
+ typedef ostreambuf_iterator<_CharT, _Traits> _Iter;
+ typedef money_put<_CharT, _Iter> _MoneyPut;
+ const _MoneyPut& __mp = use_facet<_MoneyPut>(__os.getloc());
+ const _Iter __end = __mp.put(_Iter(__os.rdbuf()), __f._M_intl,
+ __os, __os.fill(), __f._M_mon);
+ if (__end.failed())
+ __os.setstate(ios_base::badbit);
+ }
+ __catch(__cxxabiv1::__forced_unwind&)
+ {
+ __os._M_setstate(ios_base::badbit);
+ __throw_exception_again;
+ }
+ __catch(...)
+ { __os._M_setstate(ios_base::badbit); }
+ }
return __os;
}
diff --git a/libstdc++-v3/include/std/system_error b/libstdc++-v3/include/std/system_error
index 565261e709b..19482bc2181 100644
--- a/libstdc++-v3/include/std/system_error
+++ b/libstdc++-v3/include/std/system_error
@@ -361,7 +361,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __hash_base<size_t, error_code>
{
size_t
- operator()(const error_code& __e) const
+ operator()(const error_code& __e) const noexcept
{
const size_t __tmp = std::_Hash_impl::hash(__e._M_value);
return std::_Hash_impl::__hash_combine(__e._M_cat, __tmp);
diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread
index 8cc06903ebf..1d1733731bf 100644
--- a/libstdc++-v3/include/std/thread
+++ b/libstdc++-v3/include/std/thread
@@ -221,7 +221,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __hash_base<size_t, thread::id>
{
size_t
- operator()(const thread::id& __id) const
+ operator()(const thread::id& __id) const noexcept
{ return std::_Hash_impl::hash(__id._M_thread); }
};
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 51be289d506..282d4509d3a 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -69,35 +69,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __add_r_ref<_Tp&>
{ typedef _Tp& type; };
- // To work around c++/49225 aka c++/48322.
- template<typename...>
- struct __conv_types { };
-
- template<typename _Tuple1, typename _Tuple2>
- struct __one_by_one_convertible
- : public false_type { };
-
- template<typename _Tp, typename _Up>
- struct __one_by_one_convertible<__conv_types<_Tp>, __conv_types<_Up>>
- : public is_convertible<_Tp, _Up>::type { };
-
- template<typename _T1, typename... _TR, typename _U1, typename... _UR>
- struct __one_by_one_convertible<__conv_types<_T1, _TR...>,
- __conv_types<_U1, _UR...>>
- : public __and_<is_convertible<_T1, _U1>,
- __one_by_one_convertible<__conv_types<_TR...>,
- __conv_types<_UR...>>>::type
- { };
-
- template<typename _Tuple1, typename _Tuple2>
- struct __all_convertible;
-
- template<typename... _TTypes, typename... _UTypes>
- struct __all_convertible<__conv_types<_TTypes...>,
- __conv_types<_UTypes...>>
- : public __one_by_one_convertible<__conv_types<_TTypes...>,
- __conv_types<_UTypes...>>::type { };
-
template<std::size_t _Idx, typename _Head, bool _IsEmpty>
struct _Head_base;
@@ -408,11 +379,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: _Inherited(__elements...) { }
template<typename... _UElements, typename = typename
- enable_if<__and_<integral_constant<bool, sizeof...(_UElements)
- == sizeof...(_Elements)>,
- __all_convertible<__conv_types<_UElements...>,
- __conv_types<_Elements...>>
- >::value>::type>
+ enable_if<__and_<is_convertible<_UElements,
+ _Elements>...>::value>::type>
explicit
constexpr tuple(_UElements&&... __elements)
: _Inherited(std::forward<_UElements>(__elements)...) { }
@@ -422,21 +390,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr tuple(tuple&&) = default;
template<typename... _UElements, typename = typename
- enable_if<__and_<integral_constant<bool, sizeof...(_UElements)
- == sizeof...(_Elements)>,
- __all_convertible<__conv_types<const _UElements&...>,
- __conv_types<_Elements...>>
- >::value>::type>
+ enable_if<__and_<is_convertible<const _UElements&,
+ _Elements>...>::value>::type>
constexpr tuple(const tuple<_UElements...>& __in)
: _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
{ }
template<typename... _UElements, typename = typename
- enable_if<__and_<integral_constant<bool, sizeof...(_UElements)
- == sizeof...(_Elements)>,
- __all_convertible<__conv_types<_UElements...>,
- __conv_types<_Elements...>>
- >::value>::type>
+ enable_if<__and_<is_convertible<_UElements,
+ _Elements>...>::value>::type>
constexpr tuple(tuple<_UElements...>&& __in)
: _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index a0208590bb5..46e3f800cab 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -745,6 +745,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Implementation for non-reference types. To meet the proper
// variable definition semantics, we also need to test for
// is_destructible in this case.
+ // This form should be simplified by a single expression:
+ // ::delete ::new _Tp(declval<_Arg>()), see c++/51222.
struct __do_is_direct_constructible_impl
{
template<typename _Tp, typename _Arg, typename
@@ -778,9 +780,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct remove_reference;
template<typename _From, typename _To, bool
- = is_reference<_From>::value>
+ = __not_<__or_<is_void<_From>,
+ is_function<_From>>>::value>
struct __is_base_to_derived_ref;
+ // Detect whether we have a downcast situation during
+ // reference binding.
template<typename _From, typename _To>
struct __is_base_to_derived_ref<_From, _To, true>
{
@@ -803,6 +808,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
is_rvalue_reference<_To>>::value>
struct __is_lvalue_to_rvalue_ref;
+ // Detect whether we have an lvalue of non-function type
+ // bound to a reference-compatible rvalue-reference.
template<typename _From, typename _To>
struct __is_lvalue_to_rvalue_ref<_From, _To, true>
{
@@ -810,8 +817,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_From>::type>::type __src_t;
typedef typename remove_cv<typename remove_reference<
_To>::type>::type __dst_t;
- typedef __or_<is_same<__src_t, __dst_t>,
- is_base_of<__dst_t, __src_t>> type;
+ typedef __and_<__not_<is_function<__src_t>>,
+ __or_<is_same<__src_t, __dst_t>,
+ is_base_of<__dst_t, __src_t>>> type;
static constexpr bool value = type::value;
};
@@ -823,9 +831,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Here we handle direct-initialization to a reference type as
// equivalent to a static_cast modulo overshooting conversions.
// These are restricted to the following conversions:
- // a) A glvalue of a base class to a derived class reference
+ // a) A base class value to a derived class reference
// b) An lvalue to an rvalue-reference of reference-compatible
- // types
+ // types that are not functions
template<typename _Tp, typename _Arg>
struct __is_direct_constructible_ref_cast
: public __and_<__is_static_castable<_Arg, _Tp>,
@@ -850,7 +858,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Since default-construction and binary direct-initialization have
// been handled separately, the implementation of the remaining
- // n-ary construction cases is rather straightforward.
+ // n-ary construction cases is rather straightforward. We can use
+ // here a functional cast, because array types are excluded anyway
+ // and this form is never interpreted as a C cast.
struct __do_is_nary_constructible_impl
{
template<typename _Tp, typename... _Args, typename
diff --git a/libstdc++-v3/include/std/typeindex b/libstdc++-v3/include/std/typeindex
index a92c2969b97..fa07ac620e6 100644
--- a/libstdc++-v3/include/std/typeindex
+++ b/libstdc++-v3/include/std/typeindex
@@ -76,7 +76,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return !_M_target->before(*__rhs._M_target); }
size_t
- hash_code() const
+ hash_code() const noexcept
{ return _M_target->hash_code(); }
const char*
@@ -97,7 +97,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef type_index argument_type;
size_t
- operator()(const type_index& __ti) const
+ operator()(const type_index& __ti) const noexcept
{ return __ti.hash_code(); }
};
diff --git a/libstdc++-v3/include/tr1/functional b/libstdc++-v3/include/tr1/functional
index 7651326955a..ff2bd2a7134 100644
--- a/libstdc++-v3/include/tr1/functional
+++ b/libstdc++-v3/include/tr1/functional
@@ -43,9 +43,20 @@
#include <tr1/functional_hash.h>
#include <ext/type_traits.h>
#include <bits/move.h> // for std::__addressof
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+# include <type_traits> // for integral_constant, true_type, false_type
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ template<int> struct _Placeholder;
+ template<typename> class _Bind;
+ template<typename, typename> class _Bind_result;
+_GLIBCXX_END_NAMESPACE_VERSION
+#endif
+
namespace tr1
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -847,16 +858,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_END_NAMESPACE_VERSION
- /** @namespace std::placeholders
- * @brief ISO C++ 0x entities sub namespace for functional.
- *
- * Define a large number of placeholders. There is no way to
- * simplify this with variadic templates, because we're introducing
- * unique names for each.
+ /** @namespace std::tr1::placeholders
+ * @brief Sub-namespace for tr1/functional.
*/
namespace placeholders
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ /* Define a large number of placeholders. There is no way to
+ * simplify this with variadic templates, because we're introducing
+ * unique names for each.
+ */
namespace
{
_Placeholder<1> _1;
@@ -904,6 +915,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<int _Num>
const int is_placeholder<_Placeholder<_Num> >::value;
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ template<int _Num>
+ struct is_placeholder<std::_Placeholder<_Num>>
+ : std::integral_constant<int, _Num>
+ { };
+
+ template<int _Num>
+ struct is_placeholder<const std::_Placeholder<_Num>>
+ : std::integral_constant<int, _Num>
+ { };
+#endif
+
/**
* Stores a tuple of indices. Used by bind() to extract the elements
* in a tuple.
@@ -1347,6 +1370,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Signature>
const bool is_bind_expression<_Bind<_Signature> >::value;
+ /// Class template _Bind is always a bind expression.
+ template<typename _Signature>
+ struct is_bind_expression<const _Bind<_Signature> >
+ { static const bool value = true; };
+
+ template<typename _Signature>
+ const bool is_bind_expression<const _Bind<_Signature> >::value;
+
+ /// Class template _Bind is always a bind expression.
+ template<typename _Signature>
+ struct is_bind_expression<volatile _Bind<_Signature> >
+ { static const bool value = true; };
+
+ template<typename _Signature>
+ const bool is_bind_expression<volatile _Bind<_Signature> >::value;
+
+ /// Class template _Bind is always a bind expression.
+ template<typename _Signature>
+ struct is_bind_expression<const volatile _Bind<_Signature> >
+ { static const bool value = true; };
+
+ template<typename _Signature>
+ const bool is_bind_expression<const volatile _Bind<_Signature> >::value;
+
/// Class template _Bind_result is always a bind expression.
template<typename _Result, typename _Signature>
struct is_bind_expression<_Bind_result<_Result, _Signature> >
@@ -1355,6 +1402,70 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Result, typename _Signature>
const bool is_bind_expression<_Bind_result<_Result, _Signature> >::value;
+ /// Class template _Bind_result is always a bind expression.
+ template<typename _Result, typename _Signature>
+ struct is_bind_expression<const _Bind_result<_Result, _Signature> >
+ { static const bool value = true; };
+
+ template<typename _Result, typename _Signature>
+ const bool
+ is_bind_expression<const _Bind_result<_Result, _Signature> >::value;
+
+ /// Class template _Bind_result is always a bind expression.
+ template<typename _Result, typename _Signature>
+ struct is_bind_expression<volatile _Bind_result<_Result, _Signature> >
+ { static const bool value = true; };
+
+ template<typename _Result, typename _Signature>
+ const bool
+ is_bind_expression<volatile _Bind_result<_Result, _Signature> >::value;
+
+ /// Class template _Bind_result is always a bind expression.
+ template<typename _Result, typename _Signature>
+ struct
+ is_bind_expression<const volatile _Bind_result<_Result, _Signature> >
+ { static const bool value = true; };
+
+ template<typename _Result, typename _Signature>
+ const bool
+ is_bind_expression<const volatile _Bind_result<_Result,
+ _Signature> >::value;
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ template<typename _Signature>
+ struct is_bind_expression<std::_Bind<_Signature>>
+ : true_type { };
+
+ template<typename _Signature>
+ struct is_bind_expression<const std::_Bind<_Signature>>
+ : true_type { };
+
+ template<typename _Signature>
+ struct is_bind_expression<volatile std::_Bind<_Signature>>
+ : true_type { };
+
+ template<typename _Signature>
+ struct is_bind_expression<const volatile std::_Bind<_Signature>>
+ : true_type { };
+
+ template<typename _Result, typename _Signature>
+ struct is_bind_expression<std::_Bind_result<_Result, _Signature>>
+ : true_type { };
+
+ template<typename _Result, typename _Signature>
+ struct is_bind_expression<const std::_Bind_result<_Result, _Signature>>
+ : true_type { };
+
+ template<typename _Result, typename _Signature>
+ struct is_bind_expression<volatile std::_Bind_result<_Result, _Signature>>
+ : true_type { };
+
+ template<typename _Result, typename _Signature>
+ struct is_bind_expression<const volatile std::_Bind_result<_Result,
+ _Signature>>
+ : true_type { };
+#endif
+
/// bind
template<typename _Functor, typename... _ArgTypes>
inline
@@ -2147,6 +2258,59 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_END_NAMESPACE_VERSION
}
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ template<typename> struct is_placeholder;
+
+ template<int _Num>
+ struct is_placeholder<tr1::_Placeholder<_Num>>
+ : integral_constant<int, _Num>
+ { };
+
+ template<int _Num>
+ struct is_placeholder<const tr1::_Placeholder<_Num>>
+ : integral_constant<int, _Num>
+ { };
+
+ template<typename> struct is_bind_expression;
+
+ template<typename _Signature>
+ struct is_bind_expression<tr1::_Bind<_Signature>>
+ : true_type { };
+
+ template<typename _Signature>
+ struct is_bind_expression<const tr1::_Bind<_Signature>>
+ : true_type { };
+
+ template<typename _Signature>
+ struct is_bind_expression<volatile tr1::_Bind<_Signature>>
+ : true_type { };
+
+ template<typename _Signature>
+ struct is_bind_expression<const volatile tr1::_Bind<_Signature>>
+ : true_type { };
+
+ template<typename _Result, typename _Signature>
+ struct is_bind_expression<tr1::_Bind_result<_Result, _Signature>>
+ : true_type { };
+
+ template<typename _Result, typename _Signature>
+ struct is_bind_expression<const tr1::_Bind_result<_Result, _Signature>>
+ : true_type { };
+
+ template<typename _Result, typename _Signature>
+ struct is_bind_expression<volatile tr1::_Bind_result<_Result, _Signature>>
+ : true_type { };
+
+ template<typename _Result, typename _Signature>
+ struct is_bind_expression<const volatile tr1::_Bind_result<_Result,
+ _Signature>>
+ : true_type { };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+#endif
}
#endif // _GLIBCXX_TR1_FUNCTIONAL
diff --git a/libstdc++-v3/include/tr1/hashtable.h b/libstdc++-v3/include/tr1/hashtable.h
index 5d1e02c2592..5e17b238a1f 100644
--- a/libstdc++-v3/include/tr1/hashtable.h
+++ b/libstdc++-v3/include/tr1/hashtable.h
@@ -813,7 +813,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
// Find the node whose key compares equal to k, beginning the search
- // at p (usually the head of a bucket). Return nil if no node is found.
+ // at p (usually the head of a bucket). Return zero if no node is found.
template<typename _Key, typename _Value,
typename _Allocator, typename _ExtractKey, typename _Equal,
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
@@ -829,7 +829,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
for (; __p; __p = __p->_M_next)
if (this->_M_compare(__k, __code, __p))
return __p;
- return false;
+ return 0;
}
// Insert v in bucket n (assumes no element with its key already present).
diff --git a/libstdc++-v3/include/tr1/poly_hermite.tcc b/libstdc++-v3/include/tr1/poly_hermite.tcc
index e86b3777c74..95e8079d543 100644
--- a/libstdc++-v3/include/tr1/poly_hermite.tcc
+++ b/libstdc++-v3/include/tr1/poly_hermite.tcc
@@ -1,6 +1,6 @@
// Special functions -*- C++ -*-
-// Copyright (C) 2006, 2007, 2008, 2009, 2010
+// Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
@@ -84,7 +84,7 @@ namespace tr1
unsigned int __i;
for (__H_nm2 = __H_0, __H_nm1 = __H_1, __i = 2; __i <= __n; ++__i)
{
- __H_n = 2 * (__x * __H_nm1 + (__i - 1) * __H_nm2);
+ __H_n = 2 * (__x * __H_nm1 - (__i - 1) * __H_nm2);
__H_nm2 = __H_nm1;
__H_nm1 = __H_n;
}
diff --git a/libstdc++-v3/libsupc++/eh_tm.cc b/libstdc++-v3/libsupc++/eh_tm.cc
index f5815a180df..a64610283ff 100644
--- a/libstdc++-v3/libsupc++/eh_tm.cc
+++ b/libstdc++-v3/libsupc++/eh_tm.cc
@@ -45,7 +45,9 @@ free_any_cxa_exception (_Unwind_Exception *eo)
__cxa_free_dependent_exception (dep);
}
+#ifdef _GLIBCXX_ATOMIC_BUILTINS_4
if (__sync_sub_and_fetch (&h->referenceCount, 1) == 0)
+#endif
__cxa_free_exception (h + 1);
}
diff --git a/libstdc++-v3/libsupc++/typeinfo b/libstdc++-v3/libsupc++/typeinfo
index 69311d69e9a..22ef49fa7b2 100644
--- a/libstdc++-v3/libsupc++/typeinfo
+++ b/libstdc++-v3/libsupc++/typeinfo
@@ -140,7 +140,7 @@ namespace std
{ return !operator==(__arg); }
#ifdef __GXX_EXPERIMENTAL_CXX0X__
- size_t hash_code() const throw()
+ size_t hash_code() const noexcept
{
# if !__GXX_MERGED_TYPEINFO_NAMES
return _Hash_bytes(name(), __builtin_strlen(name()),
diff --git a/libstdc++-v3/scripts/run_doxygen b/libstdc++-v3/scripts/run_doxygen
index 7b601bce0a8..af2d0fc3809 100644
--- a/libstdc++-v3/scripts/run_doxygen
+++ b/libstdc++-v3/scripts/run_doxygen
@@ -267,8 +267,8 @@ done
rm stdheader
# Some of the pages for generated modules have text that confuses certain
-# implementations of man(1), e.g., Linux's. We need to have another top-level
-# *roff tag to /stop/ the .SH NAME entry.
+# implementations of man(1), e.g. on GNU/Linux. We need to have another
+# top-level *roff tag to /stop/ the .SH NAME entry.
problematic=`egrep --files-without-match '^\.SH SYNOPSIS' [A-Z]*.3`
#problematic='Containers.3 Sequences.3 Assoc_containers.3 Iterator_types.3'
diff --git a/libstdc++-v3/src/compatibility-ldbl.cc b/libstdc++-v3/src/compatibility-ldbl.cc
index a9bdb8b0986..a103856adfa 100644
--- a/libstdc++-v3/src/compatibility-ldbl.cc
+++ b/libstdc++-v3/src/compatibility-ldbl.cc
@@ -1,6 +1,6 @@
// Compatibility symbols for -mlong-double-64 compatibility -*- C++ -*-
-// Copyright (C) 2006, 2008, 2009, 2010
+// Copyright (C) 2006, 2008, 2009, 2010, 2011
// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
@@ -69,14 +69,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
// For std::tr1::hash<long double>::operator()
#define _GLIBCXX_LONG_DOUBLE_COMPAT_IMPL
-
-namespace std _GLIBCXX_VISIBILITY(default)
-{
- namespace tr1
- {
-#include "hash-long-double-aux.cc"
- }
-}
+#include "hash-long-double-tr1-aux.cc"
// std::tr1::hash<long double>::operator()
// and std::hash<long double>::operator()
diff --git a/libstdc++-v3/src/hash-long-double-aux.cc b/libstdc++-v3/src/hash-long-double-aux.cc
deleted file mode 100644
index d54d635f83e..00000000000
--- a/libstdc++-v3/src/hash-long-double-aux.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// std::hash and std::tr1::hash definitions, long double bits -*- C++ -*-
-
-// 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.
-
-// 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/>.
-
- // For long double, careful with random padding bits (e.g., on x86,
- // 10 bytes -> 12 bytes) and resort to frexp.
- template<>
- size_t
- hash<long double>::operator()(long double __val) const
- {
- // 0 and -0 both hash to zero.
- if (__val == 0.0L)
- return 0;
-
- int __exponent;
- __val = __builtin_frexpl(__val, &__exponent);
- __val = __val < 0.0l ? -(__val + 0.5l) : __val;
-
- const long double __mult = __SIZE_MAX__ + 1.0l;
- __val *= __mult;
-
- // Try to use all the bits of the mantissa (really necessary only
- // on 32-bit targets, at least for 80-bit floating point formats).
- const size_t __hibits = (size_t)__val;
- __val = (__val - (long double)__hibits) * __mult;
-
- const size_t __coeff = __SIZE_MAX__ / __LDBL_MAX_EXP__;
-
- return __hibits + (size_t)__val + __coeff * __exponent;
- }
diff --git a/libstdc++-v3/src/hash-long-double-tr1-aux.cc b/libstdc++-v3/src/hash-long-double-tr1-aux.cc
new file mode 100644
index 00000000000..70ed45bbfbe
--- /dev/null
+++ b/libstdc++-v3/src/hash-long-double-tr1-aux.cc
@@ -0,0 +1,56 @@
+// std::tr1::hash definitions, long double bits -*- 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/>.
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+ namespace tr1
+ {
+ // For long double, careful with random padding bits (e.g., on x86,
+ // 10 bytes -> 12 bytes) and resort to frexp.
+ template<>
+ size_t
+ hash<long double>::operator()(long double __val) const
+ {
+ // 0 and -0 both hash to zero.
+ if (__val == 0.0L)
+ return 0;
+
+ int __exponent;
+ __val = __builtin_frexpl(__val, &__exponent);
+ __val = __val < 0.0l ? -(__val + 0.5l) : __val;
+
+ const long double __mult = __SIZE_MAX__ + 1.0l;
+ __val *= __mult;
+
+ // Try to use all the bits of the mantissa (really necessary only
+ // on 32-bit targets, at least for 80-bit floating point formats).
+ const size_t __hibits = (size_t)__val;
+ __val = (__val - (long double)__hibits) * __mult;
+
+ const size_t __coeff = __SIZE_MAX__ / __LDBL_MAX_EXP__;
+
+ return __hibits + (size_t)__val + __coeff * __exponent;
+ }
+ }
+}
diff --git a/libstdc++-v3/src/hash_c++0x.cc b/libstdc++-v3/src/hash_c++0x.cc
index 852498df602..d685074540b 100644
--- a/libstdc++-v3/src/hash_c++0x.cc
+++ b/libstdc++-v3/src/hash_c++0x.cc
@@ -1,6 +1,6 @@
// std::hash definitions -*- C++ -*-
-// Copyright (C) 2010 Free Software Foundation, Inc.
+// 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
@@ -30,5 +30,27 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
-#include "hash-long-double-aux.cc"
+ _GLIBCXX_PURE size_t
+ hash<long double>::operator()(long double __val) const noexcept
+ {
+ // 0 and -0 both hash to zero.
+ if (__val == 0.0L)
+ return 0;
+
+ int __exponent;
+ __val = __builtin_frexpl(__val, &__exponent);
+ __val = __val < 0.0l ? -(__val + 0.5l) : __val;
+
+ const long double __mult = __SIZE_MAX__ + 1.0l;
+ __val *= __mult;
+
+ // Try to use all the bits of the mantissa (really necessary only
+ // on 32-bit targets, at least for 80-bit floating point formats).
+ const size_t __hibits = (size_t)__val;
+ __val = (__val - (long double)__hibits) * __mult;
+
+ const size_t __coeff = __SIZE_MAX__ / __LDBL_MAX_EXP__;
+
+ return __hibits + (size_t)__val + __coeff * __exponent;
+ }
}
diff --git a/libstdc++-v3/src/hash_tr1.cc b/libstdc++-v3/src/hash_tr1.cc
index e707e827a11..a5ac87e585b 100644
--- a/libstdc++-v3/src/hash_tr1.cc
+++ b/libstdc++-v3/src/hash_tr1.cc
@@ -1,6 +1,6 @@
// std::tr1::hash definitions -*- C++ -*-
-// Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+// 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
@@ -25,12 +25,12 @@
#include <string>
#include <tr1/functional>
+#include "hash-long-double-tr1-aux.cc"
+
namespace std _GLIBCXX_VISIBILITY(default)
{
namespace tr1
{
-#include "hash-long-double-aux.cc"
-
#ifndef _GLIBCXX_LONG_DOUBLE_COMPAT_IMPL
template<>
size_t
diff --git a/libstdc++-v3/testsuite/20_util/bind/cv_quals_3.cc b/libstdc++-v3/testsuite/20_util/bind/cv_quals_3.cc
new file mode 100644
index 00000000000..6affa1168e2
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/bind/cv_quals_3.cc
@@ -0,0 +1,65 @@
+// 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/>.
+
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+#include <functional>
+
+struct X
+{
+ int operator()() const { return 0; }
+ int operator()() volatile { return 1; }
+ int operator()() const volatile { return 2; }
+ void operator()() { };
+};
+
+void test01()
+{
+ static_assert( std::is_placeholder<decltype(std::placeholders::_1)>::value,
+ "decltype(_1) is a placeholder type" );
+
+ const auto b0 = std::bind(X());
+ static_assert( std::is_bind_expression<decltype(b0)>::value,
+ "const-qualified wrapper is a bind expression" );
+
+ volatile auto b1 = std::bind(X());
+ static_assert( std::is_bind_expression<decltype(b1)>::value,
+ "volatile-qualified wrapper is a bind expression" );
+
+ const volatile auto b2 = std::bind(X());
+ static_assert( std::is_bind_expression<decltype(b2)>::value,
+ "const-volatile-qualified wrapper is a bind expression" );
+
+ const auto b3 = std::bind<int>(X());
+ static_assert( std::is_bind_expression<decltype(b3)>::value,
+ "const-qualified wrapper is a bind expression" );
+
+ volatile auto b4 = std::bind<int>(X());
+ static_assert( std::is_bind_expression<decltype(b4)>::value,
+ "volatile-qualified wrapper is a bind expression" );
+
+ const volatile auto b5 = std::bind<int>(X());
+ static_assert( std::is_bind_expression<decltype(b5)>::value,
+ "const-volatile-qualified wrapper is a bind expression" );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc b/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc
index f5a08c2630a..fa2123114d5 100644
--- a/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc
@@ -29,8 +29,12 @@ int inc(int& i) { return ++i; }
void test01()
{
const int dummy = 0;
- std::bind(&inc, _1)(0); // { dg-error "no match|rvalue" }
- std::bind(&inc, std::ref(dummy))(); // { dg-error "no match|const" }
+ std::bind(&inc, _1)(0); // { dg-error "no match" }
+ // { dg-error "rvalue|const" "" { target *-*-* } 1206 }
+ // { dg-error "rvalue|const" "" { target *-*-* } 1219 }
+ // { dg-error "rvalue|const" "" { target *-*-* } 1233 }
+ // { dg-error "rvalue|const" "" { target *-*-* } 1247 }
+ std::bind(&inc, std::ref(dummy))(); // { dg-error "no match" }
}
struct Inc
diff --git a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc
index 1f4065b92a8..33ab45b4bbc 100644
--- a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc
@@ -19,7 +19,7 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-error "static assertion failed" "" { target *-*-* } 1759 }
+// { dg-error "static assertion failed" "" { target *-*-* } 1769 }
#include <utility>
diff --git a/libstdc++-v3/testsuite/20_util/is_constructible/51185.cc b/libstdc++-v3/testsuite/20_util/is_constructible/51185.cc
new file mode 100644
index 00000000000..faf3969fe83
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_constructible/51185.cc
@@ -0,0 +1,39 @@
+// { 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 <type_traits>
+
+struct A { };
+struct B : A { };
+
+// libstdc++/51185
+void f()
+{
+ static_assert(!std::is_constructible<B &&, A>(), "");
+ static_assert(!std::is_constructible<B const &&, A>(), "");
+ static_assert(!std::is_constructible<B const &&, A const>(), "");
+ static_assert(!std::is_constructible<B volatile &&, A>(), "");
+ static_assert(!std::is_constructible<B volatile &&, A volatile>(), "");
+ static_assert(!std::is_constructible<B const volatile &&, A>(), "");
+ static_assert(!std::is_constructible<B const volatile &&, A const>(), "");
+ static_assert(!std::is_constructible<B const volatile &&, A volatile>(), "");
+ static_assert(!std::is_constructible<B const volatile &&,
+ A const volatile>(), "");
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_constructible/value-2.cc b/libstdc++-v3/testsuite/20_util/is_constructible/value-2.cc
index 24fde938988..06895e32bb0 100644
--- a/libstdc++-v3/testsuite/20_util/is_constructible/value-2.cc
+++ b/libstdc++-v3/testsuite/20_util/is_constructible/value-2.cc
@@ -817,3 +817,5 @@ static_assert(!std::is_constructible<const int&, ExplicitTo<double&&>>::value,
"Error");
static_assert(!std::is_constructible<int&&, ExplicitTo<double&&>>::value,
"Error");
+
+static_assert(std::is_constructible<void(&&)(), void(&)()>::value, "Error");
diff --git a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
index d61daf35853..b8bd23f841f 100644
--- a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
@@ -48,5 +48,5 @@ void test01()
// { dg-error "required from here" "" { target *-*-* } 40 }
// { dg-error "required from here" "" { target *-*-* } 42 }
-// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1545 }
-// { dg-error "declaration of" "" { target *-*-* } 1509 }
+// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1555 }
+// { dg-error "declaration of" "" { target *-*-* } 1519 }
diff --git a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
index ee74be9f267..96940119ed9 100644
--- a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
@@ -48,5 +48,5 @@ void test01()
// { dg-error "required from here" "" { target *-*-* } 40 }
// { dg-error "required from here" "" { target *-*-* } 42 }
-// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1463 }
-// { dg-error "declaration of" "" { target *-*-* } 1427 }
+// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1473 }
+// { dg-error "declaration of" "" { target *-*-* } 1437 }
diff --git a/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc b/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc
index ad998356c83..73a0d0f7029 100644
--- a/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc
@@ -44,4 +44,4 @@ void test01()
tuple<Type> t(allocator_arg, a, 1);
}
-// { dg-error "no matching function" "" { target *-*-* } 141 }
+// { dg-error "no matching function" "" { target *-*-* } 112 }
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/moveable2.cc b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/moveable2.cc
index 13cc4e5d196..2d1b4ca86a0 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/moveable2.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/moveable2.cc
@@ -31,6 +31,7 @@ class tstring : public std::basic_string<char>
public:
tstring() : std::basic_string<char>() {}
tstring(tstring&& s) : std::basic_string<char>(std::move(s)) {}
+ tstring& operator=(tstring&& s) = default;
};
void test01()
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/moveable2.cc b/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/moveable2.cc
index e0b8b24a0cb..42026c90bd8 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/moveable2.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/moveable2.cc
@@ -31,6 +31,7 @@ class twstring : public std::basic_string<wchar_t>
public:
twstring() : std::basic_string<wchar_t>() {}
twstring(twstring&& s) : std::basic_string<wchar_t>(std::move(s)) {}
+ twstring& operator=(twstring&&) = default;
};
void test01()
diff --git a/libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr-2.cc b/libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr-2.cc
new file mode 100644
index 00000000000..14ab8e71275
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr-2.cc
@@ -0,0 +1,36 @@
+// { dg-do compile }
+// { dg-require-normal-mode "" }
+// { 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 <bitset>
+
+int main()
+{
+ // bitset base type
+ typedef std::_Base_bitset<6> bitset_base;
+ constexpr bitset_base base = bitset_base();
+
+ constexpr auto r1 __attribute__((unused)) = base._M_getword(2);
+ // constexpr auto r2 = base._M_getdata(); // error, pointer to this
+ auto r2 __attribute__((unused)) = base._M_getdata();
+ constexpr auto r3 __attribute__((unused)) = base._M_hiword();
+
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr.cc b/libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr.cc
index fc171c8238f..384f01a5dff 100644
--- a/libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr.cc
+++ b/libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr.cc
@@ -22,15 +22,6 @@
int main()
{
- // bitset base type
- typedef std::_Base_bitset<6> bitset_base;
- constexpr bitset_base base = bitset_base();
-
- constexpr auto r1 __attribute__((unused)) = base._M_getword(2);
- // constexpr auto r2 = base._M_getdata(); // error, pointer to this
- auto r2 __attribute__((unused)) = base._M_getdata();
- constexpr auto r3 __attribute__((unused)) = base._M_hiword();
-
// bitset operators
typedef std::bitset<6> bitset_type;
constexpr bitset_type a = bitset_type();
diff --git a/libstdc++-v3/testsuite/23_containers/map/modifiers/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/map/modifiers/erase/51142.cc
new file mode 100644
index 00000000000..f50b7b7e9fd
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/map/modifiers/erase/51142.cc
@@ -0,0 +1,38 @@
+// 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/>.
+//
+
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+#include <map>
+
+struct X
+{
+ template<typename T>
+ X(T&) {}
+};
+
+bool operator<(const X&, const X&) { return false; }
+
+// LWG 2059.
+void erasor(std::map<X, int>& s, X x)
+{
+ std::map<X, int>::iterator it = s.find(x);
+ if (it != s.end())
+ s.erase(it);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/multimap/modifiers/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/multimap/modifiers/erase/51142.cc
new file mode 100644
index 00000000000..ee687f77cf6
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/multimap/modifiers/erase/51142.cc
@@ -0,0 +1,38 @@
+// 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/>.
+//
+
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+#include <map>
+
+struct X
+{
+ template<typename T>
+ X(T&) {}
+};
+
+bool operator<(const X&, const X&) { return false; }
+
+// LWG 2059.
+void erasor(std::multimap<X, int>& s, X x)
+{
+ std::multimap<X, int>::iterator it = s.find(x);
+ if (it != s.end())
+ s.erase(it);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/multiset/modifiers/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/multiset/modifiers/erase/51142.cc
new file mode 100644
index 00000000000..c5beb6a8dd5
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/multiset/modifiers/erase/51142.cc
@@ -0,0 +1,38 @@
+// 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/>.
+//
+
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+#include <set>
+
+struct X
+{
+ template<typename T>
+ X(T&) {}
+};
+
+bool operator<(const X&, const X&) { return false; }
+
+// LWG 2059.
+void erasor(std::multiset<X>& s, X x)
+{
+ std::multiset<X>::iterator it = s.find(x);
+ if (it != s.end())
+ s.erase(it);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/set/modifiers/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/set/modifiers/erase/51142.cc
new file mode 100644
index 00000000000..4fb296a95fc
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/set/modifiers/erase/51142.cc
@@ -0,0 +1,38 @@
+// 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/>.
+//
+
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+#include <set>
+
+struct X
+{
+ template<typename T>
+ X(T&) {}
+};
+
+bool operator<(const X&, const X&) { return false; }
+
+// LWG 2059.
+void erasor(std::set<X>& s, X x)
+{
+ std::set<X>::iterator it = s.find(x);
+ if (it != s.end())
+ s.erase(it);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/erase/51142.cc
new file mode 100644
index 00000000000..eab637df235
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/erase/51142.cc
@@ -0,0 +1,38 @@
+// 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/>.
+//
+
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+#include <unordered_map>
+
+struct X
+{
+ template<typename T>
+ X(T&) {}
+};
+
+bool operator==(const X&, const X&) { return false; }
+
+// LWG 2059.
+void erasor(std::unordered_map<X, int>& s, X x)
+{
+ std::unordered_map<X, int>::iterator it = s.find(x);
+ if (it != s.end())
+ s.erase(it);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/erase/51142.cc
new file mode 100644
index 00000000000..678aa5dd989
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/erase/51142.cc
@@ -0,0 +1,38 @@
+// 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/>.
+//
+
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+#include <unordered_map>
+
+struct X
+{
+ template<typename T>
+ X(T&) {}
+};
+
+bool operator==(const X&, const X&) { return false; }
+
+// LWG 2059.
+void erasor(std::unordered_multimap<X, int>& s, X x)
+{
+ std::unordered_multimap<X, int>::iterator it = s.find(x);
+ if (it != s.end())
+ s.erase(it);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/copy.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/copy.cc
new file mode 100644
index 00000000000..7e50c302d11
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/copy.cc
@@ -0,0 +1,45 @@
+// { 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/>.
+
+
+// NOTE: This makes use of the fact that we know how moveable
+// is implemented on set (via swap). If the implementation changed
+// this test may begin to fail.
+
+#include <unordered_set>
+#include <utility>
+#include <testsuite_hooks.h>
+
+int main()
+{
+ bool test __attribute__((unused)) = true;
+
+ const int nb = 10000;
+ std::unordered_multiset<int> ref;
+ for (int i = 0; i != nb; ++i)
+ {
+ ref.insert(i);
+ ref.insert(i);
+ }
+
+ std::unordered_multiset<int> copy(ref);
+ VERIFY( copy.size() == ref.size() );
+ VERIFY( std::equal(ref.begin(), ref.end(), copy.begin()) );
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/1.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/1.cc
index 327dc4bd0b2..e48e31149e3 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/1.cc
@@ -23,6 +23,18 @@
#include <string>
#include <testsuite_hooks.h>
+namespace
+{
+ std::size_t
+ get_nb_bucket_elems(const std::unordered_multiset<std::string>& us)
+ {
+ std::size_t nb = 0;
+ for (std::size_t b = 0; b != us.bucket_count(); ++b)
+ nb += us.bucket_size(b);
+ return nb;
+ }
+}
+
void test01()
{
bool test __attribute__((unused)) = true;
@@ -45,14 +57,17 @@ void test01()
ms1.insert("one line behind");
ms1.insert("because to why");
VERIFY( ms1.size() == 11 );
+ VERIFY( get_nb_bucket_elems(ms1) == ms1.size() );
VERIFY( ms1.erase("eeilo") == 1 );
VERIFY( ms1.size() == 10 );
+ VERIFY( get_nb_bucket_elems(ms1) == ms1.size() );
iterator it1 = ms1.find("eeilo");
VERIFY( it1 == ms1.end() );
VERIFY( ms1.erase("tillsammans") == 1 );
VERIFY( ms1.size() == 9 );
+ VERIFY( get_nb_bucket_elems(ms1) == ms1.size() );
iterator it2 = ms1.find("tillsammans");
VERIFY( it2 == ms1.end() );
@@ -61,17 +76,20 @@ void test01()
VERIFY( it3 != ms1.end() );
VERIFY( ms1.erase(*it3) == 1 );
VERIFY( ms1.size() == 8 );
+ VERIFY( get_nb_bucket_elems(ms1) == ms1.size() );
it3 = ms1.find("belonging (no longer mix)");
VERIFY( it3 == ms1.end() );
VERIFY( !ms1.erase("abra") );
VERIFY( ms1.size() == 8 );
+ VERIFY( get_nb_bucket_elems(ms1) == ms1.size() );
VERIFY( !ms1.erase("eeilo") );
VERIFY( ms1.size() == 8 );
VERIFY( ms1.erase("because to why") == 2 );
VERIFY( ms1.size() == 6 );
+ VERIFY( get_nb_bucket_elems(ms1) == ms1.size() );
iterator it4 = ms1.find("because to why");
VERIFY( it4 == ms1.end() );
@@ -87,11 +105,13 @@ void test01()
VERIFY( ms1.erase(*it5) == 1 );
VERIFY( ms1.size() == 5 );
+ VERIFY( get_nb_bucket_elems(ms1) == ms1.size() );
it5 = ms1.find("umbra/penumbra");
VERIFY( it5 == ms1.end() );
VERIFY( ms1.erase(*it6) == 1 );
VERIFY( ms1.size() == 4 );
+ VERIFY( get_nb_bucket_elems(ms1) == ms1.size() );
it6 = ms1.find("one line behind");
VERIFY( it6 == ms1.end() );
@@ -103,6 +123,7 @@ void test01()
VERIFY( ms1.erase(*it8) == 1 );
VERIFY( ms1.size() == 3 );
+ VERIFY( get_nb_bucket_elems(ms1) == ms1.size() );
VERIFY( ++it7 == it9 );
iterator it10 = it9;
@@ -110,15 +131,18 @@ void test01()
iterator it11 = it10;
VERIFY( ms1.erase(*it9) == 1 );
+ VERIFY( get_nb_bucket_elems(ms1) == ms1.size() );
VERIFY( ms1.size() == 2 );
VERIFY( ++it10 == ms1.end() );
VERIFY( ms1.erase(ms1.begin()) != ms1.end() );
VERIFY( ms1.size() == 1 );
+ VERIFY( get_nb_bucket_elems(ms1) == ms1.size() );
VERIFY( ms1.begin() == it11 );
VERIFY( ms1.erase(*ms1.begin()) == 1 );
VERIFY( ms1.size() == 0 );
+ VERIFY( get_nb_bucket_elems(ms1) == ms1.size() );
VERIFY( ms1.begin() == ms1.end() );
}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/24061-multiset.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/24061-multiset.cc
index c5eea6eeebc..ba1659aedfd 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/24061-multiset.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/24061-multiset.cc
@@ -23,6 +23,20 @@
#include <string>
#include <testsuite_hooks.h>
+namespace
+{
+ std::size_t
+ get_nb_bucket_elems(const std::unordered_multiset<std::string>& us)
+ {
+ std::size_t nb = 0;
+ for (std::size_t b = 0; b != us.bucket_count(); ++b)
+ {
+ nb += us.bucket_size(b);
+ }
+ return nb;
+ }
+}
+
// libstdc++/24061
void test01()
{
@@ -49,6 +63,7 @@ void test01()
ms1.insert("love is not enough");
ms1.insert("every day is exactly the same");
VERIFY( ms1.size() == 13 );
+ VERIFY( get_nb_bucket_elems(ms1) == ms1.size() );
iterator it1 = ms1.begin();
++it1;
@@ -56,6 +71,7 @@ void test01()
++it2;
iterator it3 = ms1.erase(it1);
VERIFY( ms1.size() == 12 );
+ VERIFY( get_nb_bucket_elems(ms1) == ms1.size() );
VERIFY( it3 == it2 );
VERIFY( *it3 == *it2 );
@@ -68,6 +84,7 @@ void test01()
++it5;
iterator it6 = ms1.erase(it4, it5);
VERIFY( ms1.size() == 10 );
+ VERIFY( get_nb_bucket_elems(ms1) == ms1.size() );
VERIFY( it6 == it5 );
VERIFY( *it6 == *it5 );
@@ -79,6 +96,7 @@ void test01()
++it8;
const_iterator it9 = ms1.erase(it7);
VERIFY( ms1.size() == 9 );
+ VERIFY( get_nb_bucket_elems(ms1) == ms1.size() );
VERIFY( it9 == it8 );
VERIFY( *it9 == *it8 );
@@ -91,11 +109,13 @@ void test01()
++it11;
const_iterator it12 = ms1.erase(it10, it11);
VERIFY( ms1.size() == 5 );
+ VERIFY( get_nb_bucket_elems(ms1) == ms1.size() );
VERIFY( it12 == it11 );
VERIFY( *it12 == *it11 );
iterator it13 = ms1.erase(ms1.begin(), ms1.end());
VERIFY( ms1.size() == 0 );
+ VERIFY( get_nb_bucket_elems(ms1) == ms1.size() );
VERIFY( it13 == ms1.end() );
VERIFY( it13 == ms1.begin() );
}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/51142.cc
new file mode 100644
index 00000000000..4db6af0fa25
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/erase/51142.cc
@@ -0,0 +1,38 @@
+// 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/>.
+//
+
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+#include <unordered_set>
+
+struct X
+{
+ template<typename T>
+ X(T&) {}
+};
+
+bool operator==(const X&, const X&) { return false; }
+
+// LWG 2059.
+void erasor(std::unordered_multiset<X>& s, X x)
+{
+ std::unordered_multiset<X>::iterator it = s.find(x);
+ if (it != s.end())
+ s.erase(it);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_range.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_range.cc
index 571346fd5c2..59cd8c9857b 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_range.cc
@@ -25,6 +25,19 @@
#include <unordered_set>
#include <testsuite_hooks.h>
+namespace
+{
+ template <typename _Tp>
+ std::size_t
+ get_nb_bucket_elems(const std::unordered_multiset<_Tp>& us)
+ {
+ std::size_t nb = 0;
+ for (std::size_t b = 0; b != us.bucket_count(); ++b)
+ nb += us.bucket_size(b);
+ return nb;
+ }
+}
+
void test01()
{
bool test __attribute__((unused)) = true;
@@ -38,8 +51,9 @@ void test01()
"magenta", "yellow", "orange", "pink", "gray" };
s.insert(A+0, A+N);
- VERIFY(s.size() == static_cast<unsigned int>(N));
- VERIFY(std::distance(s.begin(), s.end()) == N);
+ VERIFY( s.size() == static_cast<unsigned int>(N) );
+ VERIFY( std::distance(s.begin(), s.end()) == N );
+ VERIFY( get_nb_bucket_elems(s) == N );
for (int i = 0; i < N; ++i) {
std::string str = A[i];
@@ -62,6 +76,7 @@ void test02()
s.insert(A+0, A+N);
VERIFY(s.size() == static_cast<unsigned int>(N));
VERIFY(std::distance(s.begin(), s.end()) == N);
+ VERIFY( get_nb_bucket_elems(s) == N );
VERIFY(std::count(s.begin(), s.end(), 2) == 1);
VERIFY(std::count(s.begin(), s.end(), 3) == 1);
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single.cc
index f275e9a9bdd..ebc38b2402a 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single.cc
@@ -24,6 +24,19 @@
#include <unordered_set>
#include <testsuite_hooks.h>
+namespace
+{
+ std::size_t
+ get_nb_bucket_elems(const std::unordered_multiset<std::string>& us)
+ {
+ std::size_t nb = 0;
+ for (std::size_t b = 0; b != us.bucket_count(); ++b)
+ nb += us.bucket_size(b);
+ return nb;
+ }
+}
+
+
void test01()
{
bool test __attribute__((unused)) = true;
@@ -33,7 +46,8 @@ void test01()
VERIFY(s.empty());
Set::iterator i = s.insert("abcde");
- VERIFY(s.size() == 1);
+ VERIFY( s.size() == 1 );
+ VERIFY( get_nb_bucket_elems(s) == 1 );
VERIFY(std::distance(s.begin(), s.end()) == 1);
VERIFY(i == s.begin());
VERIFY(*i == "abcde");
@@ -50,6 +64,7 @@ void test02()
s.insert("abcde");
Set::iterator i = s.insert("abcde");
VERIFY(s.size() == 2);
+ VERIFY( get_nb_bucket_elems(s) == 2 );
VERIFY(std::distance(s.begin(), s.end()) == 2);
VERIFY(*i == "abcde");
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single_move.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single_move.cc
index 14b8e16817a..4dc9fba5b68 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single_move.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/insert/multiset_single_move.cc
@@ -26,6 +26,19 @@
#include <testsuite_hooks.h>
#include <testsuite_rvalref.h>
+namespace
+{
+ template <typename _Tp>
+ std::size_t
+ get_nb_bucket_elems(const std::unordered_multiset<_Tp>& us)
+ {
+ std::size_t nb = 0;
+ for (std::size_t b = 0; b != us.bucket_count(); ++b)
+ nb += us.bucket_size(b);
+ return nb;
+ }
+}
+
void test01()
{
bool test __attribute__((unused)) = true;
@@ -37,6 +50,7 @@ void test01()
Set::iterator i = s.insert(rvalstruct(1));
VERIFY( s.size() == 1 );
+ VERIFY( get_nb_bucket_elems(s) == 1 );
VERIFY( std::distance(s.begin(), s.end()) == 1 );
VERIFY( i == s.begin() );
VERIFY( (*i).val == 1 );
@@ -54,6 +68,7 @@ void test02()
s.insert(rvalstruct(2));
Set::iterator i = s.insert(rvalstruct(2));
VERIFY( s.size() == 2 );
+ VERIFY( get_nb_bucket_elems(s) == 2 );
VERIFY( std::distance(s.begin(), s.end()) == 2 );
VERIFY( (*i).val == 2 );
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/erase/51142.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/erase/51142.cc
new file mode 100644
index 00000000000..14864604289
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/erase/51142.cc
@@ -0,0 +1,38 @@
+// 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/>.
+//
+
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+#include <unordered_set>
+
+struct X
+{
+ template<typename T>
+ X(T&) {}
+};
+
+bool operator==(const X&, const X&) { return false; }
+
+// LWG 2059.
+void erasor(std::unordered_set<X>& s, X x)
+{
+ std::unordered_set<X>::iterator it = s.find(x);
+ if (it != s.end())
+ s.erase(it);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/hash_policy/rehash.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/hash_policy/rehash.cc
new file mode 100644
index 00000000000..91dc0fd402e
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/hash_policy/rehash.cc
@@ -0,0 +1,62 @@
+// 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/>.
+//
+// { dg-options "-std=gnu++0x" }
+
+#include <unordered_set>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ std::unordered_set<int> us;
+ typedef typename std::unordered_set<int>::size_type size_type;
+ bool rehashed = false;
+ for (int i = 0; i != 100000; ++i)
+ {
+ size_type bkt_count = us.bucket_count();
+ us.insert(i);
+ if (bkt_count != us.bucket_count())
+ {
+ // Container has been rehashed, lets check that it won't be rehash again
+ // if we remove and restore the last 2 inserted elements:
+ rehashed = true;
+ bkt_count = us.bucket_count();
+ VERIFY( us.erase(i) == 1 );
+ VERIFY( bkt_count == us.bucket_count() );
+ if (i > 0)
+ {
+ VERIFY( us.erase(i - 1) == 1 );
+ VERIFY( bkt_count == us.bucket_count() );
+
+ VERIFY( us.insert(i - 1).second );
+ VERIFY( bkt_count == us.bucket_count() );
+ }
+ VERIFY( us.insert(i).second );
+ VERIFY( bkt_count == us.bucket_count() );
+ }
+ }
+
+ // At lest we check a rehash once:
+ VERIFY( rehashed );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/instantiation_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/instantiation_neg.cc
new file mode 100644
index 00000000000..aa52e6b07d4
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/instantiation_neg.cc
@@ -0,0 +1,41 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+// { dg-require-normal-mode "" }
+
+// 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 Pred the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR 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/>.
+
+// { dg-error "static assertion failed" "" { target *-*-* } 177 }
+
+#include <unordered_set>
+
+namespace
+{
+ struct hash_without_noexcept
+ {
+ std::size_t operator() (int) const
+ { return 0; }
+ };
+}
+
+void
+test01()
+{
+ std::__unordered_set<int, hash_without_noexcept,
+ std::equal_to<int>, std::allocator<int>,
+ false> us;
+}
diff --git a/libstdc++-v3/testsuite/27_io/manipulators/extended/get_money/char/51288.cc b/libstdc++-v3/testsuite/27_io/manipulators/extended/get_money/char/51288.cc
new file mode 100644
index 00000000000..281a2e2d39c
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/manipulators/extended/get_money/char/51288.cc
@@ -0,0 +1,48 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-require-namedlocale "en_US.UTF-8" }
+
+// 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 <sstream>
+#include <iomanip>
+#include <testsuite_hooks.h>
+
+// libstdc++/51288
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ std::locale loc_us = std::locale("en_US.UTF-8");
+
+ std::istringstream iss;
+ iss.imbue(loc_us);
+
+ iss.str(" $1.23");
+
+ std::string str;
+ iss >> std::get_money(str);
+
+ VERIFY( str == "123" );
+ VERIFY( iss.eof() );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/manipulators/extended/get_money/wchar_t/51288.cc b/libstdc++-v3/testsuite/27_io/manipulators/extended/get_money/wchar_t/51288.cc
new file mode 100644
index 00000000000..2ec02302c31
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/manipulators/extended/get_money/wchar_t/51288.cc
@@ -0,0 +1,48 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-require-namedlocale "en_US.UTF-8" }
+
+// 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 <sstream>
+#include <iomanip>
+#include <testsuite_hooks.h>
+
+// libstdc++/51288
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ std::locale loc_us = std::locale("en_US.UTF-8");
+
+ std::wistringstream iss;
+ iss.imbue(loc_us);
+
+ iss.str(L" $1.23");
+
+ std::wstring str;
+ iss >> std::get_money(str);
+
+ VERIFY( str == L"123" );
+ VERIFY( iss.eof() );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/manipulators/extended/put_money/char/51288.cc b/libstdc++-v3/testsuite/27_io/manipulators/extended/put_money/char/51288.cc
new file mode 100644
index 00000000000..d2cc9cb7012
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/manipulators/extended/put_money/char/51288.cc
@@ -0,0 +1,49 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-require-namedlocale "en_US.UTF-8" }
+
+// 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 <sstream>
+#include <iomanip>
+#include <testsuite_hooks.h>
+
+// libstdc++/51288
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ std::locale loc_us = std::locale("en_US.UTF-8");
+
+ std::ostringstream oss;
+ oss.imbue(loc_us);
+
+ const std::string str("123");
+
+ oss.setstate(std::ios_base::failbit);
+
+ oss << std::put_money(str);
+
+ VERIFY( oss.str().empty() );
+ VERIFY( oss.fail() );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/manipulators/extended/put_money/wchar_t/51288.cc b/libstdc++-v3/testsuite/27_io/manipulators/extended/put_money/wchar_t/51288.cc
new file mode 100644
index 00000000000..548c0a7c2b4
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/manipulators/extended/put_money/wchar_t/51288.cc
@@ -0,0 +1,49 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-require-namedlocale "en_US.UTF-8" }
+
+// 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 <sstream>
+#include <iomanip>
+#include <testsuite_hooks.h>
+
+// libstdc++/51288
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ std::locale loc_us = std::locale("en_US.UTF-8");
+
+ std::wostringstream oss;
+ oss.imbue(loc_us);
+
+ const std::wstring str(L"123");
+
+ oss.setstate(std::ios_base::failbit);
+
+ oss << std::put_money(str);
+
+ VERIFY( oss.str().empty() );
+ VERIFY( oss.fail() );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/30_threads/future/cons/constexpr.cc b/libstdc++-v3/testsuite/30_threads/future/cons/constexpr.cc
index a56d5852424..d35e6aaba35 100644
--- a/libstdc++-v3/testsuite/30_threads/future/cons/constexpr.cc
+++ b/libstdc++-v3/testsuite/30_threads/future/cons/constexpr.cc
@@ -1,12 +1,12 @@
// { dg-do compile }
-// { dg-options "-std=gnu++0x -fno-inline -save-temps" }
+// { dg-options "-std=gnu++0x -fno-inline -save-temps -g0" }
// { dg-require-cstdint "" }
// { dg-require-gthreads "" }
// { dg-require-atomic-builtins "" }
// { dg-final { scan-assembler-not "_ZNSt6futureIvEC2Ev" } }
// { dg-final { scan-assembler-not "_ZNSt6futureIiEC2Ev" } }
-// Copyright (C) 2010 Free Software Foundation, Inc.
+// 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
diff --git a/libstdc++-v3/testsuite/30_threads/shared_future/cons/constexpr.cc b/libstdc++-v3/testsuite/30_threads/shared_future/cons/constexpr.cc
index 159077bc820..6f06ffeb647 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_future/cons/constexpr.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_future/cons/constexpr.cc
@@ -1,12 +1,12 @@
// { dg-do compile }
-// { dg-options "-std=gnu++0x -fno-inline -save-temps" }
+// { dg-options "-std=gnu++0x -fno-inline -save-temps -g0" }
// { dg-require-cstdint "" }
// { dg-require-gthreads "" }
// { dg-require-atomic-builtins "" }
// { dg-final { scan-assembler-not "_ZNSt13shared_futureIvEC2Ev" } }
// { dg-final { scan-assembler-not "_ZNSt13shared_futureIiEC2Ev" } }
-// Copyright (C) 2010 Free Software Foundation, Inc.
+// 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
diff --git a/libstdc++-v3/testsuite/30_threads/thread/native_handle/typesizes.cc b/libstdc++-v3/testsuite/30_threads/thread/native_handle/typesizes.cc
index 602d40ff46a..049443543f2 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/native_handle/typesizes.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/native_handle/typesizes.cc
@@ -1,7 +1,7 @@
-// { dg-do run { target *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* alpha*-*-osf* mips-sgi-irix6* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-linux* alpha*-*-osf* mips-sgi-irix6* } }
+// { dg-do run { target *-*-linux* *-*-solaris* *-*-cygwin mips-sgi-irix6* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-linux* mips-sgi-irix6* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
-// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
+// { dg-options " -std=gnu++0x " { target *-*-cygwin } }
// { dg-require-cstdint "" }
// { dg-require-gthreads "" }
diff --git a/libstdc++-v3/testsuite/performance/23_containers/copy_construct/unordered_set.cc b/libstdc++-v3/testsuite/performance/23_containers/copy_construct/unordered_set.cc
new file mode 100644
index 00000000000..f214d1dd666
--- /dev/null
+++ b/libstdc++-v3/testsuite/performance/23_containers/copy_construct/unordered_set.cc
@@ -0,0 +1,43 @@
+// { 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 <unordered_set>
+#include <testsuite_performance.h>
+
+int main()
+{
+ using namespace __gnu_test;
+
+ time_counter time;
+ resource_counter resource;
+
+ std::unordered_set<int> ref;
+ for (int i = 0; i != 500000; ++i)
+ ref.insert(i);
+
+ start_counters(time, resource);
+
+ for (unsigned i = 0; i < 500; ++i)
+ std::unordered_set<int> v(ref);
+
+ stop_counters(time, resource);
+ report_performance(__FILE__, "unordered_set<int> copy", time, resource);
+
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/tr1/3_function_objects/bind/cv_quals.cc b/libstdc++-v3/testsuite/tr1/3_function_objects/bind/cv_quals.cc
new file mode 100644
index 00000000000..5ea373647fc
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr1/3_function_objects/bind/cv_quals.cc
@@ -0,0 +1,53 @@
+// 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/>.
+
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+#include <tr1/functional>
+
+struct X
+{
+ int operator()() const { return 0; }
+ int operator()() volatile { return 1; }
+ int operator()() const volatile { return 2; }
+ void operator()() { };
+};
+
+void test01()
+{
+ static_assert( std::tr1::is_placeholder<__typeof(std::tr1::placeholders::_1)>::value,
+ "decltype(_1) is a placeholder type" );
+
+ const auto b0 = std::tr1::bind(X());
+ static_assert( std::tr1::is_bind_expression<__typeof(b0)>::value,
+ "const-qualified wrapper is a bind expression" );
+
+ volatile auto b1 = std::tr1::bind(X());
+ static_assert( std::tr1::is_bind_expression<__typeof(b1)>::value,
+ "volatile-qualified wrapper is a bind expression" );
+
+ const volatile auto b2 = std::tr1::bind(X());
+ static_assert( std::tr1::is_bind_expression<__typeof(b2)>::value,
+ "const-volatile-qualified wrapper is a bind expression" );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/tr1/3_function_objects/bind/mixed.cc b/libstdc++-v3/testsuite/tr1/3_function_objects/bind/mixed.cc
new file mode 100644
index 00000000000..2d96bb7ec86
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr1/3_function_objects/bind/mixed.cc
@@ -0,0 +1,139 @@
+// { dg-options "-std=gnu++11" }
+// 2011-11-20 Jonathan Wakely <jwakely.gcc -at- gmail.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/>.
+
+// 3.6 function object binders
+#include <tr1/functional>
+#include <functional>
+#include <testsuite_hooks.h>
+
+// std::tr1::bind and std::bind should work together
+
+namespace p1 = std::placeholders;
+namespace p2 = std::tr1::placeholders;
+
+using std::multiplies;
+using std::minus;
+
+void test01()
+{
+ static_assert( std::is_placeholder<decltype(p2::_2)>::value == 2,
+ "TR1 placeholder is a std placeholder" );
+ static_assert( std::tr1::is_placeholder<decltype(p1::_1)>::value == 1,
+ "std placeholder is a TR2 placeholder" );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+
+ auto b1 = std::bind(minus<int>(), 6, p2::_2);
+ auto b2 = std::tr1::bind(minus<int>(), 6, p1::_2);
+
+ int five = 5;
+ int seven = 7;
+
+ VERIFY( std::tr1::bind(multiplies<int>(), p1::_1, b1)(five, seven) == -5 );
+ VERIFY( std::bind(multiplies<int>(), p2::_1, b2)(seven, five) == 7 );
+
+ VERIFY( std::tr1::bind<int>(multiplies<int>(), p1::_1, b1)(five, seven) == -5 );
+ VERIFY( std::bind<int>(multiplies<int>(), p2::_1, b2)(seven, five) == 7 );
+
+ static_assert( std::is_bind_expression<decltype(b2)>::value,
+ "TR1 bind expression is a std bind expression" );
+ static_assert( std::tr1::is_bind_expression<decltype(b1)>::value,
+ "std bind expression is a TR2 bind expression" );
+
+ const auto c1 = b1;
+ const auto c2 = b2;
+
+ static_assert( std::is_bind_expression<decltype(c2)>::value,
+ "const TR1 bind expression is a std bind expression" );
+ static_assert( std::tr1::is_bind_expression<decltype(c1)>::value,
+ "const std bind expression is a TR2 bind expression" );
+
+ volatile auto v1 = b1;
+ volatile auto v2 = b2;
+
+ static_assert( std::is_bind_expression<decltype(v2)>::value,
+ "volatile TR1 bind expression is a std bind expression" );
+ static_assert( std::tr1::is_bind_expression<decltype(v1)>::value,
+ "volatile std bind expression is a TR2 bind expression" );
+
+ const volatile auto cv1 = b1;
+ const volatile auto cv2 = b2;
+
+ static_assert( std::is_bind_expression<decltype(cv2)>::value,
+ "const volatile TR1 bind expression is a std bind expression" );
+ static_assert( std::tr1::is_bind_expression<decltype(cv1)>::value,
+ "const volatile std bind expression is a TR2 bind expression" );
+}
+
+void test03()
+{
+ bool test __attribute__((unused)) = true;
+
+ auto b1 = std::bind<int>(minus<int>(), 6, p2::_2);
+ auto b2 = std::tr1::bind<int>(minus<int>(), 6, p1::_2);
+
+ int five = 5;
+ int seven = 7;
+ VERIFY( std::tr1::bind(multiplies<int>(), p1::_1, b1)(five, seven) == -5 );
+ VERIFY( std::bind(multiplies<int>(), p2::_1, b2)(seven, five) == 7 );
+
+ VERIFY( std::tr1::bind<int>(multiplies<int>(), p1::_1, b1)(five, seven) == -5 );
+ VERIFY( std::bind<int>(multiplies<int>(), p2::_1, b2)(seven, five) == 7 );
+
+ static_assert( std::is_bind_expression<decltype(b2)>::value,
+ "TR1 bind<R> expression is a std bind expression" );
+ static_assert( std::tr1::is_bind_expression<decltype(b1)>::value,
+ "std bind<R> expression is a TR2 bind expression" );
+
+ const auto c1 = b1;
+ const auto c2 = b2;
+
+ static_assert( std::is_bind_expression<decltype(c2)>::value,
+ "const TR1 bind<R> expression is a std bind expression" );
+ static_assert( std::tr1::is_bind_expression<decltype(c1)>::value,
+ "const std bind<R> expression is a TR2 bind expression" );
+
+ volatile auto v1 = b1;
+ volatile auto v2 = b2;
+
+ static_assert( std::is_bind_expression<decltype(v2)>::value,
+ "volatile TR1 bind<R> expression is a std bind expression" );
+ static_assert( std::tr1::is_bind_expression<decltype(v1)>::value,
+ "volatile std bind<R> expression is a TR2 bind expression" );
+
+ const volatile auto cv1 = b1;
+ const volatile auto cv2 = b2;
+
+ static_assert( std::is_bind_expression<decltype(cv2)>::value,
+ "const volatile TR1 bind<R> expression is a std bind expression" );
+ static_assert( std::tr1::is_bind_expression<decltype(cv1)>::value,
+ "const volatile std bind<R> expression is a TR2 bind expression" );
+}
+
+int main()
+{
+ test01();
+ test02();
+ test03();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/util/testsuite_tr1.h b/libstdc++-v3/testsuite/util/testsuite_tr1.h
index f0638960b27..1452e3e9f88 100644
--- a/libstdc++-v3/testsuite/util/testsuite_tr1.h
+++ b/libstdc++-v3/testsuite/util/testsuite_tr1.h
@@ -199,6 +199,7 @@ namespace __gnu_test
struct NoexceptMoveConsClass
{
NoexceptMoveConsClass(NoexceptMoveConsClass&&) noexcept(true);
+ NoexceptMoveConsClass& operator=(NoexceptMoveConsClass&&) = default;
};
struct ExceptMoveConsClass
@@ -220,6 +221,7 @@ namespace __gnu_test
struct NoexceptMoveAssignClass
{
+ NoexceptMoveAssignClass(NoexceptMoveAssignClass&&) = default;
NoexceptMoveAssignClass&
operator=(NoexceptMoveAssignClass&&) noexcept(true);
};
diff --git a/libtool.m4 b/libtool.m4
index 71bcee83c87..67321a7d070 100644
--- a/libtool.m4
+++ b/libtool.m4
@@ -2273,7 +2273,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[[123]]*) objformat=aout ;;
+ freebsd[[23]].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -2291,7 +2291,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[[01]]* | freebsdelf3.[[01]]*)
@@ -4804,7 +4804,7 @@ _LT_EOF
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_minus_L, $1)=yes
@@ -5751,7 +5751,7 @@ if test "$_lt_caught_CXX_error" != yes; then
esac
;;
- freebsd[[12]]*)
+ freebsd2.*)
# C++ shared libraries reported to be fairly broken before
# switch to ELF
_LT_TAGVAR(ld_shlibs, $1)=no
diff --git a/lto-plugin/ChangeLog b/lto-plugin/ChangeLog
index bf149e4b880..aa98f64f5a3 100644
--- a/lto-plugin/ChangeLog
+++ b/lto-plugin/ChangeLog
@@ -1,3 +1,7 @@
+2011-11-21 Andreas Tobler <andreast@fgznet.ch>
+
+ * configure: Regenerate.
+
2011-10-02 Jan Hubicka <jh@suse.cz>
PR lto/47247
diff --git a/lto-plugin/configure b/lto-plugin/configure
index 9815917f8fd..48b414e99f7 100755
--- a/lto-plugin/configure
+++ b/lto-plugin/configure
@@ -8773,7 +8773,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct=yes
hardcode_minus_L=yes
@@ -9686,7 +9686,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -9704,7 +9704,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
diff --git a/maintainer-scripts/ChangeLog b/maintainer-scripts/ChangeLog
index b0c363860e2..e98f0af5086 100644
--- a/maintainer-scripts/ChangeLog
+++ b/maintainer-scripts/ChangeLog
@@ -1,3 +1,8 @@
+2011-11-21 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * update_web_docs_svn: Make $DOCSDIR group writable after
+ creating it.
+
2011-06-27 Richard Guenther <rguenther@suse.de>
* update_version_svn (IGNORE_BRANCHES): Add gcc-4_3-branch.
diff --git a/maintainer-scripts/update_web_docs_svn b/maintainer-scripts/update_web_docs_svn
index a0551615d7d..cfc33c42bf5 100755
--- a/maintainer-scripts/update_web_docs_svn
+++ b/maintainer-scripts/update_web_docs_svn
@@ -93,6 +93,7 @@ fi
if [ ! -d $DOCSDIR ]; then
mkdir $DOCSDIR
+ chmod g+w $DOCSDIR
fi
if [ -z "$RELEASE" ]; then
diff --git a/zlib/ChangeLog.gcj b/zlib/ChangeLog.gcj
index d3b34b5fb52..7afe93793c2 100644
--- a/zlib/ChangeLog.gcj
+++ b/zlib/ChangeLog.gcj
@@ -1,3 +1,7 @@
+2011-11-21 Andreas Tobler <andreast@fgznet.ch>
+
+ * configure: Regenerate.
+
2011-02-13 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
* configure: Regenerate.
diff --git a/zlib/configure b/zlib/configure
index 8be4e40c82c..f7fe2b7bd51 100755
--- a/zlib/configure
+++ b/zlib/configure
@@ -8600,7 +8600,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
- freebsd2*)
+ freebsd2.*)
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct=yes
hardcode_minus_L=yes
@@ -9516,7 +9516,7 @@ freebsd* | dragonfly*)
objformat=`/usr/bin/objformat`
else
case $host_os in
- freebsd[123]*) objformat=aout ;;
+ freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
@@ -9534,7 +9534,7 @@ freebsd* | dragonfly*)
esac
shlibpath_var=LD_LIBRARY_PATH
case $host_os in
- freebsd2*)
+ freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)